diff options
| author | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2023-06-21 00:00:00 +0000 |
|---|---|---|
| committer | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2023-12-17 14:59:19 +0500 |
| commit | 5b39dc76f1bc82f941d5c800ab9f34407a06b53a (patch) | |
| tree | fe5e17420300b715021a76328444088d32047963 /CPP/Windows/Menu.cpp | |
| parent | 93be7d4abfd4233228f58ee1fbbcd76d91be66a4 (diff) | |
| download | 7zip-5b39dc76f1bc82f941d5c800ab9f34407a06b53a.tar.gz 7zip-5b39dc76f1bc82f941d5c800ab9f34407a06b53a.tar.bz2 7zip-5b39dc76f1bc82f941d5c800ab9f34407a06b53a.zip | |
23.0123.01
Diffstat (limited to 'CPP/Windows/Menu.cpp')
| -rw-r--r-- | CPP/Windows/Menu.cpp | 155 |
1 files changed, 102 insertions, 53 deletions
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: | |||
| 22 | HBITMAP hbmpItem; | 22 | HBITMAP hbmpItem; |
| 23 | #endif | 23 | #endif |
| 24 | If we compile the source code with (WINVER >= 0x0500), some functions | 24 | If we compile the source code with (WINVER >= 0x0500), some functions |
| 25 | will not work at NT 4.0, if cbSize is set as sizeof(MENUITEMINFO*). | 25 | will not work at NT4, if cbSize is set as sizeof(MENUITEMINFO). |
| 26 | So we use size of old version of structure. */ | 26 | So we use size of old version of structure in some conditions. |
| 27 | Win98 probably supports full structure including hbmpItem. | ||
| 28 | |||
| 29 | We have 2 ways to get/set string in menu item: | ||
| 30 | win95/NT4: we must use MIIM_TYPE only. | ||
| 31 | MIIM_TYPE : Retrieves or sets the fType and dwTypeData members. | ||
| 32 | win98/win2000: there are new flags that can be used instead of MIIM_TYPE: | ||
| 33 | MIIM_FTYPE : Retrieves or sets the fType member. | ||
| 34 | MIIM_STRING : Retrieves or sets the dwTypeData member. | ||
| 35 | |||
| 36 | Windows versions probably support MIIM_TYPE flag, if we set MENUITEMINFO::cbSize | ||
| 37 | as sizeof of old (small) MENUITEMINFO that doesn't include (hbmpItem) field. | ||
| 38 | But do all Windows versions support old MIIM_TYPE flag, if we use | ||
| 39 | MENUITEMINFO::cbSize as sizeof of new (big) MENUITEMINFO including (hbmpItem) field ? | ||
| 40 | win10 probably supports any combination of small/big (cbSize) and old/new MIIM_TYPE/MIIM_STRING. | ||
| 41 | */ | ||
| 27 | 42 | ||
| 28 | #if defined(UNDER_CE) || defined(_WIN64) || (WINVER < 0x0500) | 43 | #if defined(UNDER_CE) || defined(_WIN64) || (WINVER < 0x0500) |
| 29 | #ifndef _UNICODE | 44 | #ifndef _UNICODE |
| @@ -36,20 +51,31 @@ So we use size of old version of structure. */ | |||
| 36 | #define my_compatib_MENUITEMINFOA_size MY_STRUCT_SIZE_BEFORE(MENUITEMINFOA, hbmpItem) | 51 | #define my_compatib_MENUITEMINFOA_size MY_STRUCT_SIZE_BEFORE(MENUITEMINFOA, hbmpItem) |
| 37 | #endif | 52 | #endif |
| 38 | #define my_compatib_MENUITEMINFOW_size MY_STRUCT_SIZE_BEFORE(MENUITEMINFOW, hbmpItem) | 53 | #define my_compatib_MENUITEMINFOW_size MY_STRUCT_SIZE_BEFORE(MENUITEMINFOW, hbmpItem) |
| 54 | #if defined(__clang__) && __clang_major__ >= 13 | ||
| 55 | // error : performing pointer subtraction with a null pointer may have undefined behavior | ||
| 56 | #pragma GCC diagnostic ignored "-Wnull-pointer-subtraction" | ||
| 39 | #endif | 57 | #endif |
| 58 | #endif | ||
| 59 | |||
| 60 | |||
| 61 | #define COPY_MENUITEM_field(d, s, name) \ | ||
| 62 | d.name = s.name; | ||
| 63 | |||
| 64 | #define COPY_MENUITEM_fields(d, s) \ | ||
| 65 | COPY_MENUITEM_field(d, s, fMask) \ | ||
| 66 | COPY_MENUITEM_field(d, s, fType) \ | ||
| 67 | COPY_MENUITEM_field(d, s, fState) \ | ||
| 68 | COPY_MENUITEM_field(d, s, wID) \ | ||
| 69 | COPY_MENUITEM_field(d, s, hSubMenu) \ | ||
| 70 | COPY_MENUITEM_field(d, s, hbmpChecked) \ | ||
| 71 | COPY_MENUITEM_field(d, s, hbmpUnchecked) \ | ||
| 72 | COPY_MENUITEM_field(d, s, dwItemData) \ | ||
| 40 | 73 | ||
| 41 | static void ConvertItemToSysForm(const CMenuItem &item, MENUITEMINFOW &si) | 74 | static void ConvertItemToSysForm(const CMenuItem &item, MENUITEMINFOW &si) |
| 42 | { | 75 | { |
| 43 | ZeroMemory(&si, sizeof(si)); | 76 | ZeroMemory(&si, sizeof(si)); |
| 44 | si.cbSize = my_compatib_MENUITEMINFOW_size; // sizeof(si); | 77 | si.cbSize = my_compatib_MENUITEMINFOW_size; // sizeof(si); |
| 45 | si.fMask = item.fMask; | 78 | COPY_MENUITEM_fields(si, item) |
| 46 | si.fType = item.fType; | ||
| 47 | si.fState = item.fState; | ||
| 48 | si.wID = item.wID; | ||
| 49 | si.hSubMenu = item.hSubMenu; | ||
| 50 | si.hbmpChecked = item.hbmpChecked; | ||
| 51 | si.hbmpUnchecked = item.hbmpUnchecked; | ||
| 52 | si.dwItemData = item.dwItemData; | ||
| 53 | } | 79 | } |
| 54 | 80 | ||
| 55 | #ifndef _UNICODE | 81 | #ifndef _UNICODE |
| @@ -57,62 +83,63 @@ static void ConvertItemToSysForm(const CMenuItem &item, MENUITEMINFOA &si) | |||
| 57 | { | 83 | { |
| 58 | ZeroMemory(&si, sizeof(si)); | 84 | ZeroMemory(&si, sizeof(si)); |
| 59 | si.cbSize = my_compatib_MENUITEMINFOA_size; // sizeof(si); | 85 | si.cbSize = my_compatib_MENUITEMINFOA_size; // sizeof(si); |
| 60 | si.fMask = item.fMask; | 86 | COPY_MENUITEM_fields(si, item) |
| 61 | si.fType = item.fType; | ||
| 62 | si.fState = item.fState; | ||
| 63 | si.wID = item.wID; | ||
| 64 | si.hSubMenu = item.hSubMenu; | ||
| 65 | si.hbmpChecked = item.hbmpChecked; | ||
| 66 | si.hbmpUnchecked = item.hbmpUnchecked; | ||
| 67 | si.dwItemData = item.dwItemData; | ||
| 68 | } | 87 | } |
| 69 | #endif | 88 | #endif |
| 70 | 89 | ||
| 71 | static void ConvertItemToMyForm(const MENUITEMINFOW &si, CMenuItem &item) | 90 | static void ConvertItemToMyForm(const MENUITEMINFOW &si, CMenuItem &item) |
| 72 | { | 91 | { |
| 73 | item.fMask = si.fMask; | 92 | COPY_MENUITEM_fields(item, si) |
| 74 | item.fType = si.fType; | ||
| 75 | item.fState = si.fState; | ||
| 76 | item.wID = si.wID; | ||
| 77 | item.hSubMenu = si.hSubMenu; | ||
| 78 | item.hbmpChecked = si.hbmpChecked; | ||
| 79 | item.hbmpUnchecked = si.hbmpUnchecked; | ||
| 80 | item.dwItemData = si.dwItemData; | ||
| 81 | } | 93 | } |
| 82 | 94 | ||
| 83 | #ifndef _UNICODE | 95 | #ifndef _UNICODE |
| 84 | static void ConvertItemToMyForm(const MENUITEMINFOA &si, CMenuItem &item) | 96 | static void ConvertItemToMyForm(const MENUITEMINFOA &si, CMenuItem &item) |
| 85 | { | 97 | { |
| 86 | item.fMask = si.fMask; | 98 | COPY_MENUITEM_fields(item, si) |
| 87 | item.fType = si.fType; | ||
| 88 | item.fState = si.fState; | ||
| 89 | item.wID = si.wID; | ||
| 90 | item.hSubMenu = si.hSubMenu; | ||
| 91 | item.hbmpChecked = si.hbmpChecked; | ||
| 92 | item.hbmpUnchecked = si.hbmpUnchecked; | ||
| 93 | item.dwItemData = si.dwItemData; | ||
| 94 | } | 99 | } |
| 95 | #endif | 100 | #endif |
| 96 | 101 | ||
| 97 | bool CMenu::GetItem(UINT itemIndex, bool byPosition, CMenuItem &item) | 102 | |
| 103 | bool CMenu::GetItem(UINT itemIndex, bool byPosition, CMenuItem &item) const | ||
| 98 | { | 104 | { |
| 99 | const UINT kMaxSize = 512; | 105 | item.StringValue.Empty(); |
| 106 | const unsigned kMaxSize = 512; | ||
| 100 | #ifndef _UNICODE | 107 | #ifndef _UNICODE |
| 101 | if (!g_IsNT) | 108 | if (!g_IsNT) |
| 102 | { | 109 | { |
| 103 | CHAR s[kMaxSize + 1]; | ||
| 104 | MENUITEMINFOA si; | 110 | MENUITEMINFOA si; |
| 105 | ConvertItemToSysForm(item, si); | 111 | ConvertItemToSysForm(item, si); |
| 106 | if (item.IsString()) | 112 | const bool isString = item.IsString(); |
| 113 | unsigned bufSize = kMaxSize; | ||
| 114 | AString a; | ||
| 115 | if (isString) | ||
| 107 | { | 116 | { |
| 108 | si.cch = kMaxSize; | 117 | si.cch = bufSize; |
| 109 | si.dwTypeData = s; | 118 | si.dwTypeData = a.GetBuf(bufSize); |
| 110 | } | 119 | } |
| 111 | if (GetItemInfo(itemIndex, byPosition, &si)) | 120 | bool res = GetItemInfo(itemIndex, byPosition, &si); |
| 121 | if (isString) | ||
| 122 | a.ReleaseBuf_CalcLen(bufSize); | ||
| 123 | if (!res) | ||
| 124 | return false; | ||
| 112 | { | 125 | { |
| 126 | if (isString && si.cch >= bufSize - 1) | ||
| 127 | { | ||
| 128 | si.dwTypeData = NULL; | ||
| 129 | res = GetItemInfo(itemIndex, byPosition, &si); | ||
| 130 | if (!res) | ||
| 131 | return false; | ||
| 132 | si.cch++; | ||
| 133 | bufSize = si.cch; | ||
| 134 | si.dwTypeData = a.GetBuf(bufSize); | ||
| 135 | res = GetItemInfo(itemIndex, byPosition, &si); | ||
| 136 | a.ReleaseBuf_CalcLen(bufSize); | ||
| 137 | if (!res) | ||
| 138 | return false; | ||
| 139 | } | ||
| 113 | ConvertItemToMyForm(si, item); | 140 | ConvertItemToMyForm(si, item); |
| 114 | if (item.IsString()) | 141 | if (isString) |
| 115 | item.StringValue = GetUnicodeString(s); | 142 | item.StringValue = GetUnicodeString(a); |
| 116 | return true; | 143 | return true; |
| 117 | } | 144 | } |
| 118 | } | 145 | } |
| @@ -120,24 +147,45 @@ bool CMenu::GetItem(UINT itemIndex, bool byPosition, CMenuItem &item) | |||
| 120 | #endif | 147 | #endif |
| 121 | { | 148 | { |
| 122 | wchar_t s[kMaxSize + 1]; | 149 | wchar_t s[kMaxSize + 1]; |
| 150 | s[0] = 0; | ||
| 123 | MENUITEMINFOW si; | 151 | MENUITEMINFOW si; |
| 124 | ConvertItemToSysForm(item, si); | 152 | ConvertItemToSysForm(item, si); |
| 125 | if (item.IsString()) | 153 | const bool isString = item.IsString(); |
| 154 | unsigned bufSize = kMaxSize; | ||
| 155 | if (isString) | ||
| 126 | { | 156 | { |
| 127 | si.cch = kMaxSize; | 157 | si.cch = bufSize; |
| 128 | si.dwTypeData = s; | 158 | si.dwTypeData = s; |
| 129 | } | 159 | } |
| 130 | if (GetItemInfo(itemIndex, byPosition, &si)) | 160 | bool res = GetItemInfo(itemIndex, byPosition, &si); |
| 161 | if (!res) | ||
| 162 | return false; | ||
| 163 | if (isString) | ||
| 131 | { | 164 | { |
| 132 | ConvertItemToMyForm(si, item); | 165 | s[Z7_ARRAY_SIZE(s) - 1] = 0; |
| 133 | if (item.IsString()) | 166 | item.StringValue = s; |
| 134 | item.StringValue = s; | 167 | if (si.cch >= bufSize - 1) |
| 135 | return true; | 168 | { |
| 169 | si.dwTypeData = NULL; | ||
| 170 | res = GetItemInfo(itemIndex, byPosition, &si); | ||
| 171 | if (!res) | ||
| 172 | return false; | ||
| 173 | si.cch++; | ||
| 174 | bufSize = si.cch; | ||
| 175 | si.dwTypeData = item.StringValue.GetBuf(bufSize); | ||
| 176 | res = GetItemInfo(itemIndex, byPosition, &si); | ||
| 177 | item.StringValue.ReleaseBuf_CalcLen(bufSize); | ||
| 178 | if (!res) | ||
| 179 | return false; | ||
| 180 | } | ||
| 181 | // if (item.StringValue.Len() != si.cch) throw 123; // for debug | ||
| 136 | } | 182 | } |
| 183 | ConvertItemToMyForm(si, item); | ||
| 184 | return true; | ||
| 137 | } | 185 | } |
| 138 | return false; | ||
| 139 | } | 186 | } |
| 140 | 187 | ||
| 188 | |||
| 141 | bool CMenu::SetItem(UINT itemIndex, bool byPosition, const CMenuItem &item) | 189 | bool CMenu::SetItem(UINT itemIndex, bool byPosition, const CMenuItem &item) |
| 142 | { | 190 | { |
| 143 | #ifndef _UNICODE | 191 | #ifndef _UNICODE |
| @@ -164,6 +212,7 @@ bool CMenu::SetItem(UINT itemIndex, bool byPosition, const CMenuItem &item) | |||
| 164 | } | 212 | } |
| 165 | } | 213 | } |
| 166 | 214 | ||
| 215 | |||
| 167 | bool CMenu::InsertItem(UINT itemIndex, bool byPosition, const CMenuItem &item) | 216 | bool CMenu::InsertItem(UINT itemIndex, bool byPosition, const CMenuItem &item) |
| 168 | { | 217 | { |
| 169 | #ifndef _UNICODE | 218 | #ifndef _UNICODE |
| @@ -188,11 +237,11 @@ bool CMenu::InsertItem(UINT itemIndex, bool byPosition, const CMenuItem &item) | |||
| 188 | si.dwTypeData = item.StringValue.Ptr_non_const(); | 237 | si.dwTypeData = item.StringValue.Ptr_non_const(); |
| 189 | #ifdef UNDER_CE | 238 | #ifdef UNDER_CE |
| 190 | UINT flags = (item.fType & MFT_SEPARATOR) ? MF_SEPARATOR : MF_STRING; | 239 | UINT flags = (item.fType & MFT_SEPARATOR) ? MF_SEPARATOR : MF_STRING; |
| 191 | UINT id = item.wID; | 240 | UINT_PTR id = item.wID; |
| 192 | if ((item.fMask & MIIM_SUBMENU) != 0) | 241 | if ((item.fMask & MIIM_SUBMENU) != 0) |
| 193 | { | 242 | { |
| 194 | flags |= MF_POPUP; | 243 | flags |= MF_POPUP; |
| 195 | id = (UINT)item.hSubMenu; | 244 | id = (UINT_PTR)item.hSubMenu; |
| 196 | } | 245 | } |
| 197 | if (!Insert(itemIndex, flags | (byPosition ? MF_BYPOSITION : MF_BYCOMMAND), id, item.StringValue)) | 246 | if (!Insert(itemIndex, flags | (byPosition ? MF_BYPOSITION : MF_BYCOMMAND), id, item.StringValue)) |
| 198 | return false; | 247 | return false; |
