From 5b39dc76f1bc82f941d5c800ab9f34407a06b53a Mon Sep 17 00:00:00 2001 From: Igor Pavlov <87184205+ip7z@users.noreply.github.com> Date: Wed, 21 Jun 2023 00:00:00 +0000 Subject: 23.01 --- CPP/Windows/Menu.cpp | 155 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 102 insertions(+), 53 deletions(-) (limited to 'CPP/Windows/Menu.cpp') diff --git a/CPP/Windows/Menu.cpp b/CPP/Windows/Menu.cpp index 3ad6953..af54c66 100644 --- a/CPP/Windows/Menu.cpp +++ b/CPP/Windows/Menu.cpp @@ -22,8 +22,23 @@ contain additional member: HBITMAP hbmpItem; #endif If we compile the source code with (WINVER >= 0x0500), some functions -will not work at NT 4.0, if cbSize is set as sizeof(MENUITEMINFO*). -So we use size of old version of structure. */ +will not work at NT4, if cbSize is set as sizeof(MENUITEMINFO). +So we use size of old version of structure in some conditions. +Win98 probably supports full structure including hbmpItem. + +We have 2 ways to get/set string in menu item: +win95/NT4: we must use MIIM_TYPE only. + MIIM_TYPE : Retrieves or sets the fType and dwTypeData members. +win98/win2000: there are new flags that can be used instead of MIIM_TYPE: + MIIM_FTYPE : Retrieves or sets the fType member. + MIIM_STRING : Retrieves or sets the dwTypeData member. + +Windows versions probably support MIIM_TYPE flag, if we set MENUITEMINFO::cbSize +as sizeof of old (small) MENUITEMINFO that doesn't include (hbmpItem) field. +But do all Windows versions support old MIIM_TYPE flag, if we use +MENUITEMINFO::cbSize as sizeof of new (big) MENUITEMINFO including (hbmpItem) field ? +win10 probably supports any combination of small/big (cbSize) and old/new MIIM_TYPE/MIIM_STRING. +*/ #if defined(UNDER_CE) || defined(_WIN64) || (WINVER < 0x0500) #ifndef _UNICODE @@ -36,20 +51,31 @@ So we use size of old version of structure. */ #define my_compatib_MENUITEMINFOA_size MY_STRUCT_SIZE_BEFORE(MENUITEMINFOA, hbmpItem) #endif #define my_compatib_MENUITEMINFOW_size MY_STRUCT_SIZE_BEFORE(MENUITEMINFOW, hbmpItem) +#if defined(__clang__) && __clang_major__ >= 13 +// error : performing pointer subtraction with a null pointer may have undefined behavior +#pragma GCC diagnostic ignored "-Wnull-pointer-subtraction" #endif +#endif + + +#define COPY_MENUITEM_field(d, s, name) \ + d.name = s.name; + +#define COPY_MENUITEM_fields(d, s) \ + COPY_MENUITEM_field(d, s, fMask) \ + COPY_MENUITEM_field(d, s, fType) \ + COPY_MENUITEM_field(d, s, fState) \ + COPY_MENUITEM_field(d, s, wID) \ + COPY_MENUITEM_field(d, s, hSubMenu) \ + COPY_MENUITEM_field(d, s, hbmpChecked) \ + COPY_MENUITEM_field(d, s, hbmpUnchecked) \ + COPY_MENUITEM_field(d, s, dwItemData) \ static void ConvertItemToSysForm(const CMenuItem &item, MENUITEMINFOW &si) { ZeroMemory(&si, sizeof(si)); si.cbSize = my_compatib_MENUITEMINFOW_size; // sizeof(si); - si.fMask = item.fMask; - si.fType = item.fType; - si.fState = item.fState; - si.wID = item.wID; - si.hSubMenu = item.hSubMenu; - si.hbmpChecked = item.hbmpChecked; - si.hbmpUnchecked = item.hbmpUnchecked; - si.dwItemData = item.dwItemData; + COPY_MENUITEM_fields(si, item) } #ifndef _UNICODE @@ -57,62 +83,63 @@ static void ConvertItemToSysForm(const CMenuItem &item, MENUITEMINFOA &si) { ZeroMemory(&si, sizeof(si)); si.cbSize = my_compatib_MENUITEMINFOA_size; // sizeof(si); - si.fMask = item.fMask; - si.fType = item.fType; - si.fState = item.fState; - si.wID = item.wID; - si.hSubMenu = item.hSubMenu; - si.hbmpChecked = item.hbmpChecked; - si.hbmpUnchecked = item.hbmpUnchecked; - si.dwItemData = item.dwItemData; + COPY_MENUITEM_fields(si, item) } #endif static void ConvertItemToMyForm(const MENUITEMINFOW &si, CMenuItem &item) { - item.fMask = si.fMask; - item.fType = si.fType; - item.fState = si.fState; - item.wID = si.wID; - item.hSubMenu = si.hSubMenu; - item.hbmpChecked = si.hbmpChecked; - item.hbmpUnchecked = si.hbmpUnchecked; - item.dwItemData = si.dwItemData; + COPY_MENUITEM_fields(item, si) } #ifndef _UNICODE static void ConvertItemToMyForm(const MENUITEMINFOA &si, CMenuItem &item) { - item.fMask = si.fMask; - item.fType = si.fType; - item.fState = si.fState; - item.wID = si.wID; - item.hSubMenu = si.hSubMenu; - item.hbmpChecked = si.hbmpChecked; - item.hbmpUnchecked = si.hbmpUnchecked; - item.dwItemData = si.dwItemData; + COPY_MENUITEM_fields(item, si) } #endif -bool CMenu::GetItem(UINT itemIndex, bool byPosition, CMenuItem &item) + +bool CMenu::GetItem(UINT itemIndex, bool byPosition, CMenuItem &item) const { - const UINT kMaxSize = 512; + item.StringValue.Empty(); + const unsigned kMaxSize = 512; #ifndef _UNICODE if (!g_IsNT) { - CHAR s[kMaxSize + 1]; MENUITEMINFOA si; ConvertItemToSysForm(item, si); - if (item.IsString()) + const bool isString = item.IsString(); + unsigned bufSize = kMaxSize; + AString a; + if (isString) { - si.cch = kMaxSize; - si.dwTypeData = s; + si.cch = bufSize; + si.dwTypeData = a.GetBuf(bufSize); } - if (GetItemInfo(itemIndex, byPosition, &si)) + bool res = GetItemInfo(itemIndex, byPosition, &si); + if (isString) + a.ReleaseBuf_CalcLen(bufSize); + if (!res) + return false; { + if (isString && si.cch >= bufSize - 1) + { + si.dwTypeData = NULL; + res = GetItemInfo(itemIndex, byPosition, &si); + if (!res) + return false; + si.cch++; + bufSize = si.cch; + si.dwTypeData = a.GetBuf(bufSize); + res = GetItemInfo(itemIndex, byPosition, &si); + a.ReleaseBuf_CalcLen(bufSize); + if (!res) + return false; + } ConvertItemToMyForm(si, item); - if (item.IsString()) - item.StringValue = GetUnicodeString(s); + if (isString) + item.StringValue = GetUnicodeString(a); return true; } } @@ -120,24 +147,45 @@ bool CMenu::GetItem(UINT itemIndex, bool byPosition, CMenuItem &item) #endif { wchar_t s[kMaxSize + 1]; + s[0] = 0; MENUITEMINFOW si; ConvertItemToSysForm(item, si); - if (item.IsString()) + const bool isString = item.IsString(); + unsigned bufSize = kMaxSize; + if (isString) { - si.cch = kMaxSize; + si.cch = bufSize; si.dwTypeData = s; } - if (GetItemInfo(itemIndex, byPosition, &si)) + bool res = GetItemInfo(itemIndex, byPosition, &si); + if (!res) + return false; + if (isString) { - ConvertItemToMyForm(si, item); - if (item.IsString()) - item.StringValue = s; - return true; + s[Z7_ARRAY_SIZE(s) - 1] = 0; + item.StringValue = s; + if (si.cch >= bufSize - 1) + { + si.dwTypeData = NULL; + res = GetItemInfo(itemIndex, byPosition, &si); + if (!res) + return false; + si.cch++; + bufSize = si.cch; + si.dwTypeData = item.StringValue.GetBuf(bufSize); + res = GetItemInfo(itemIndex, byPosition, &si); + item.StringValue.ReleaseBuf_CalcLen(bufSize); + if (!res) + return false; + } + // if (item.StringValue.Len() != si.cch) throw 123; // for debug } + ConvertItemToMyForm(si, item); + return true; } - return false; } + bool CMenu::SetItem(UINT itemIndex, bool byPosition, const CMenuItem &item) { #ifndef _UNICODE @@ -164,6 +212,7 @@ bool CMenu::SetItem(UINT itemIndex, bool byPosition, const CMenuItem &item) } } + bool CMenu::InsertItem(UINT itemIndex, bool byPosition, const CMenuItem &item) { #ifndef _UNICODE @@ -188,11 +237,11 @@ bool CMenu::InsertItem(UINT itemIndex, bool byPosition, const CMenuItem &item) si.dwTypeData = item.StringValue.Ptr_non_const(); #ifdef UNDER_CE UINT flags = (item.fType & MFT_SEPARATOR) ? MF_SEPARATOR : MF_STRING; - UINT id = item.wID; + UINT_PTR id = item.wID; if ((item.fMask & MIIM_SUBMENU) != 0) { flags |= MF_POPUP; - id = (UINT)item.hSubMenu; + id = (UINT_PTR)item.hSubMenu; } if (!Insert(itemIndex, flags | (byPosition ? MF_BYPOSITION : MF_BYCOMMAND), id, item.StringValue)) return false; -- cgit v1.2.3-55-g6feb