Проблемы с уведомлениями общего управления Windows TreeView и многобайтовым набором символов

Я столкнулся со странной проблемой при использовании TreeView Common Control в приложении Windows, написанном на C ++, и с помощью Windows API (без MFC или другого!):
Два важных уведомления TVN_ITEMCHANGED и TVN_ITEMCHANGING (доступны начиная с Windows Vista) отправляются только в том случае, если загружена версия 6.0 файла ComCtl32.dll (путем убеждения компоновщика сделать это через манифест). А ТАКЖЕ если используется набор символов Unicode.
Использование многобайтового набора символов приводит к исчезновению двух упомянутых выше уведомлений.
Использование Unicode и версии 5.82 ComCtl32.dll дает тот же результат.
Я использую Windows 7 x64 и Visual Studio 2010, кстати.

Ниже вы найдете «минимальный» (> 180 строк кода: /) рабочий пример. Сборка в Visual Studio 2010 с использованием набора символов Unicode (Свойства конфигурации> Общие> Набор символов) заставляет программу работать должным образом, но использование многобайтового набора символов приводит к исчезновению TVN_ITEMCHANGED и TVN_ITEMCHANGING. Другие уведомления приходят в любом случае.

Я что-то упустил или столкнулся с ошибкой в ​​реализации Common Controls? Я искренне надеюсь, что это мое прежнее предположение, и я очень ценю ваши ответы и идеи по этому вопросу!

С наилучшими пожеланиями,
Д. Фельдманн

#include <Windows.h>
#include <CommCtrl.h>

#include <iostream>

#pragma comment(linker, "\"/manifestdependency:type='win32'\
name='Microsoft.Windows.Common-Controls'\
version='6.0.0.0'\
processorArchitecture='*'\
publicKeyToken='6595b64144ccf1df'\
language='*'\"")

HINSTANCE g_hInst = 0;
HWND hwndTV_ = 0;

bool setupTreeView(HWND hwnd)
{
RECT rc = {0};
GetClientRect(hwnd, &rc);

DWORD style = WS_CHILD | WS_VISIBLE | WS_OVERLAPPED | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT;
hwndTV_ = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, 0, style,
10, 10, (rc.right - rc.left) - 20, (rc.bottom - rc.top) - 20,
hwnd, (HMENU) 0xDF, g_hInst, 0);

if (! hwndTV_)
return false;

style |= TVS_CHECKBOXES;
SetWindowLong(hwndTV_, GWL_STYLE, style);

HIMAGELIST hil = ImageList_Create(24, 24, ILC_COLOR | ILC_COLOR32, 2, 0);
const int img1 = ImageList_AddIcon(hil, LoadIcon(0, IDI_QUESTION));
const int img2 = ImageList_AddIcon(hil, LoadIcon(0, IDI_INFORMATION));
SendMessage(hwndTV_, TVM_SETIMAGELIST, TVSIL_NORMAL, (LPARAM) hil);

TVINSERTSTRUCT tvis = {0};
tvis.hParent =  TVI_ROOT;
tvis.hInsertAfter = TVI_ROOT;
tvis.item.mask = TVIF_TEXT | TVIF_STATE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
tvis.item.cchTextMax = 5;
tvis.item.pszText = TEXT("root\0");
tvis.item.state = (2 << 12) | TVIS_EXPANDED;
tvis.item.stateMask = TVIS_STATEIMAGEMASK | TVIS_EXPANDED;
tvis.item.iImage = img1;
tvis.item.iSelectedImage = img2;
HTREEITEM hRoot = (HTREEITEM) SendMessage(hwndTV_, TVM_INSERTITEM, 0, (LPARAM) &tvis);

tvis.hParent = hRoot;
tvis.hInsertAfter = TVI_LAST;
tvis.item.cchTextMax = 7;
tvis.item.pszText = TEXT("item 1\0");
SendMessage(hwndTV_, TVM_INSERTITEM, 0, (LPARAM) &tvis);

tvis.item.pszText = TEXT("item 2\0");
SendMessage(hwndTV_, TVM_INSERTITEM, 0, (LPARAM) &tvis);

return true;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
LRESULT res = 0u;
bool handled = true;
switch (msg)
{
case WM_CLOSE:
PostQuitMessage(0);
break;

case WM_CREATE:
setupTreeView(hwnd);
break;

case WM_NOTIFY:
{
NMHDR* const nmhdr = (NMHDR*)lParam;
switch (nmhdr->code)
{
case NM_CUSTOMDRAW:
std::cout << "NM_CUSTOMDRAW\n";
break;

case NM_CLICK:
std::cout << "NM_CLICK\n";
break;

case TVN_ITEMCHANGING:
std::cout << "!!! TVN_ITEMCHANGING !!!\n";
break;

case TVN_ITEMCHANGED:
std::cout << "!!! TVN_ITEMCHANGED !!!\n";
break;

case TVN_SELCHANGED:
std::cout << "TVN_SELCHANGED\n";
break;

case TVN_SELCHANGING:
std::cout << "TVN_SELCHANGING\n";
break;

case TVN_ITEMEXPANDED:
std::cout << "TVN_ITEMEXPANDED\n";
break;

case TVN_ITEMEXPANDING:
std::cout << "TVN_ITEMEXPANDING\n";
break;

default:
break;
}   // switch (
break;
}

default:
handled = false;
break;
}   // switch (msg

if (! handled)
res = DefWindowProc(hwnd, msg, wParam, lParam);
return res;
}

int run(HINSTANCE hInst)
{
g_hInst = hInst;

WNDCLASSEX wndCls = {0};
wndCls.cbSize = sizeof(WNDCLASSEX);
wndCls.cbClsExtra = 0;
wndCls.cbWndExtra = 0;
wndCls.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wndCls.hCursor = LoadCursor(0, IDC_HAND);
wndCls.hIcon = LoadIcon(0, IDI_WINLOGO);
wndCls.hIconSm = LoadIcon(0, IDI_WINLOGO);
wndCls.hInstance = g_hInst;
wndCls.lpfnWndProc = WindowProc;
wndCls.lpszClassName = TEXT("TestWindowClass");
wndCls.lpszMenuName = 0;
wndCls.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
RegisterClassEx(&wndCls);

INITCOMMONCONTROLSEX cc = {0};
cc.dwSize = sizeof(INITCOMMONCONTROLSEX);
cc.dwICC = ICC_TREEVIEW_CLASSES;
InitCommonControlsEx(&cc);

HWND hwnd = CreateWindowEx(0, TEXT("TestWindowClass"), TEXT("Test TreeView"),
WS_VISIBLE | WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION, CW_USEDEFAULT,
CW_USEDEFAULT, 400, 300, NULL, NULL, hInst, 0);

MSG msg = {0};
for (BOOL res = TRUE; res != 0; )
{
res = GetMessage(&msg, 0, 0, 0);
if (res != -1)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

if (msg.message == WM_QUIT)
res = 0;
}

HIMAGELIST hil = (HIMAGELIST) SendMessage(hwndTV_, TVM_GETIMAGELIST, (WPARAM) TVSIL_NORMAL, 0);
if (hil)
ImageList_Destroy(hil);

UnregisterClass(TEXT("TestWindowClass"), g_hInst);

return 0;
}

// Please build using /subsystem:console
int main(int /*argc*/, char** /*argv*/)
{
return run(GetModuleHandle(0));
}

0

Решение

Они не исчезают, вы просто не ищете их в своем WindowProc(), Как и многие API, уведомления также могут иметь версии Ansi и Unicode, но вы ищете только одну или другую версию в зависимости от того, компилируете ли вы для MBCS или Unicode. Ansi TreeView может получать уведомления Unicode и наоборот. Вы должны искать оба A а также W версии уведомлений и обрабатывать их соответственно:

switch (nmhdr->code)
{
...

case TVN_ITEMCHANGINGA:
std::cout << "!!! TVN_ITEMCHANGINGA !!!\n";
break;

case TVN_ITEMCHANGINGW:
std::cout << "!!! TVN_ITEMCHANGINGW !!!\n";
break;

case TVN_ITEMCHANGEDA:
std::cout << "!!! TVN_ITEMCHANGEDA !!!\n";
break;

case TVN_ITEMCHANGEDW:
std::cout << "!!! TVN_ITEMCHANGEDA !!!\n";
break;

case TVN_SELCHANGEDA:
std::cout << "TVN_SELCHANGEDA\n";
break;

case TVN_SELCHANGEDW:
std::cout << "TVN_SELCHANGEDW\n";
break;

case TVN_SELCHANGINGA:
std::cout << "TVN_SELCHANGINGA\n";
break;

case TVN_SELCHANGINGW:
std::cout << "TVN_SELCHANGINGW\n";
break;

case TVN_ITEMEXPANDEDA:
std::cout << "TVN_ITEMEXPANDEDA\n";
break;

case TVN_ITEMEXPANDEDW:
std::cout << "TVN_ITEMEXPANDEDW\n";
break;

case TVN_ITEMEXPANDINGA:
std::cout << "TVN_ITEMEXPANDINGA\n";
break;

case TVN_ITEMEXPANDINGW:
std::cout << "TVN_ITEMEXPANDINGW\n";
break;

...
}
0

Другие решения


По вопросам рекламы ammmcru@yandex.ru
Adblock
detector