Не работает переключение раскладок в Edit

Тема в разделе "WASM.WIN32", создана пользователем proc, 13 ноя 2009.

  1. proc

    proc New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    8
    Добрый день,

    Есть проблема - не работает переключение раскладок клавиатуры при фокусе в окне Edit.

    Родительское окно создаю так:

    Код (Text):
    1. HWND hWnd = CreateWindowExA(WS_EX_APPWINDOW,
    2.          szWndClassName, "", WS_VISIBLE | WS_OVERLAPPEDWINDOW, 100, 100, 600, 300,
    3.          hwParent, 0, 0, 0);
    Edit создается в обработчике WM_CREATE так:

    Код (Text):
    1.   g_hwEdit = CreateWindowExA(0, szEdit, 0, WS_CHILD | ES_MULTILINE | ES_WANTRETURN | ES_AUTOVSCROLL | WS_VSCROLL, 0, 0, 0, 0, hWnd, (HMENU)(MY_ED_MSG), 0, 0);
    далее, устанавливаем его размеры:

    Код (Text):
    1. SetWindowPos(g_hwEdit, 0, 25, rect.bottom - YMIN + 320, rect.right - XMIN + 266, 102, SWP_NOZORDER);
    Spy++ не показывает входящих сообщений WM_INPUTLANGCHANGE ни в родительском окне, ни в Edit'е.

    Если я создаю диалог, бросаю на него Edit и использую свою оконную функцию (обработчик) как обработчик диалога (с заменой типа функции LRESULT на INT_PTR) - все переключается нормально.
    Но основная цель - сделать как раз без использования диалогов, поставляемых из ресурсов.
    Не знаете ли вы, в чем может быть проблема?
    Спасибо.
     
  2. maksim_

    maksim_ New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2009
    Сообщения:
    263
    единственное что приходит в голову - сравни стили диалогового эдита и твоего каким-нибудь WinSpy. ещё меня настораживает вот эта фраза:
    ты, случаем WM_INPUTLANGCHANGE не перехватываешь?
     
  3. proc

    proc New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    8
    maksim_
    Не перехватываю. Пробовал - управление туда не приходит :dntknw:
    Спаем сравнивал - стили совпадают у Edit'ов, но у основного окна при создании в режиме диалога добавляются несколько DS_* стилей: DS_SETFONT | DS_SYSFONT.
    При этом, если edit создавать на диалоге вручную, то все обрабатывается нормально.
    А если вызвать контекстное меню в edit, и нажать комбинацию клавиш, переключающих раскладку - то она переключается!
     
  4. maksim_

    maksim_ New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2009
    Сообщения:
    263
    скопировал код из msdn - всё работает норм.
    Код (Text):
    1. LRESULT CALLBACK MainWndProc(
    2.     HWND hwnd,        // handle to window
    3.     UINT uMsg,        // message identifier
    4.     WPARAM wParam,    // first message parameter
    5.     LPARAM lParam)    // second message parameter
    6. {
    7.  
    8.     switch (uMsg)
    9.     {
    10.         case WM_CREATE:
    11.             CreateWindowEx(0, L"edit", L"edit1", WS_CHILD | WS_VISIBLE, 10, 10, 200, 50, hwnd, NULL, NULL, NULL);
    12.             // Initialize the window.
    13.             return 0;
    14.  
    15.         case WM_PAINT:
    16.             // Paint the window's client area.
    17.             return 0;
    18.  
    19.         case WM_SIZE:
    20.             // Set the size and position of the window.
    21.             return 0;
    22.  
    23.         case WM_DESTROY:
    24.             // Clean up window-specific data objects.
    25.             return 0;
    26.  
    27.         //
    28.         // Process other messages.
    29.         //
    30.  
    31.         default:
    32.             return DefWindowProc(hwnd, uMsg, wParam, lParam);
    33.     }
    34.     return 0;
    35. }
    36.  
    37.  
    38. BOOL InitApplication(HINSTANCE hinstance)
    39. {
    40.     WNDCLASSEX wcx;
    41.  
    42.     // Fill in the window class structure with parameters
    43.     // that describe the main window.
    44.  
    45.     wcx.cbSize = sizeof(wcx);          // size of structure
    46.     wcx.style = CS_HREDRAW |
    47.         CS_VREDRAW;                    // redraw if size changes
    48.     wcx.lpfnWndProc = MainWndProc;     // points to window procedure
    49.     wcx.cbClsExtra = 0;                // no extra class memory
    50.     wcx.cbWndExtra = 0;                // no extra window memory
    51.     wcx.hInstance = hinstance;         // handle to instance
    52.     wcx.hIcon = LoadIcon(NULL,
    53.         IDI_APPLICATION);              // predefined app. icon
    54.     wcx.hCursor = LoadCursor(NULL,
    55.         IDC_ARROW);                    // predefined arrow
    56.     wcx.hbrBackground = (HBRUSH)GetStockObject(
    57.         WHITE_BRUSH);                  // white background brush
    58.     wcx.lpszMenuName =  L"MainMenu";    // name of menu resource
    59.     wcx.lpszClassName = L"MainWClass";  // name of window class
    60.     wcx.hIconSm = (HICON)LoadImage(hinstance, // small class icon
    61.         MAKEINTRESOURCE(5),
    62.         IMAGE_ICON,
    63.         GetSystemMetrics(SM_CXSMICON),
    64.         GetSystemMetrics(SM_CYSMICON),
    65.         LR_DEFAULTCOLOR);
    66.  
    67.     // Register the window class.
    68.  
    69.     return RegisterClassEx(&wcx);
    70. }
    71.  
    72. BOOL InitInstance(HINSTANCE hinstance, int nCmdShow)
    73. {
    74.     HWND hwnd;
    75.     HINSTANCE hinst;
    76.  
    77.     // Save the application-instance handle.
    78.  
    79.     hinst = GetModuleHandle(0);
    80.  
    81.     // Create the main window.
    82.  
    83.     hwnd = CreateWindow(
    84.         L"MainWClass",        // name of window class
    85.         L"Sample",            // title-bar string
    86.         WS_OVERLAPPEDWINDOW, // top-level window
    87.         CW_USEDEFAULT,       // default horizontal position
    88.         CW_USEDEFAULT,       // default vertical position
    89.         CW_USEDEFAULT,       // default width
    90.         CW_USEDEFAULT,       // default height
    91.         (HWND) NULL,         // no owner window
    92.         (HMENU) NULL,        // use class menu
    93.         hinstance,           // handle to application instance
    94.         (LPVOID) NULL);      // no window-creation data
    95.  
    96.     if (!hwnd)
    97.         return FALSE;
    98.  
    99.     // Show the window and send a WM_PAINT message to the window
    100.     // procedure.
    101.  
    102.     ShowWindow(hwnd, nCmdShow);
    103.     UpdateWindow(hwnd);
    104.     return TRUE;
    105.  
    106. }
    107.  
    108. BOOL Main()
    109. {
    110.     MSG msg;
    111.     HINSTANCE hinstance = GetModuleHandle(0);
    112.  
    113.     if (!InitApplication(hinstance))
    114.         return FALSE;
    115.  
    116.     if (!InitInstance(hinstance, SW_SHOWNORMAL))
    117.         return FALSE;
    118.  
    119.     BOOL fGotMessage;
    120.     while ((fGotMessage = GetMessage(&msg, (HWND) NULL, 0, 0)) != 0 && fGotMessage != -1)
    121.     {
    122.         TranslateMessage(&msg);
    123.         DispatchMessage(&msg);
    124.     }
    125.     return msg.wParam;
    126. }
     
  5. G13

    G13 New Member

    Публикаций:
    0
    Регистрация:
    24 мар 2006
    Сообщения:
    499
    proc
    Покажите обработчик оконной процедуры. Что происходит, когда приходит WM_INPUTLANGCHANGEREQUEST?
     
  6. proc

    proc New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    8
    G13

    Обработчик оконной процедуры следующий (для уменьшения места и улучшения читабельности не относящиеся к делу фрагменты кода были удалены):

    Код (Text):
    1. LRESULT __stdcall ChatWndFun(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
    2.  
    3.     HWND hwTemp;
    4.     int iLength;
    5.     char * pText;
    6.     NMHDR * hdr;
    7.     LPNMITEMACTIVATE lpnmia;
    8.     PAINTSTRUCT ps;
    9.     HDC dc;
    10.     LPMEASUREITEMSTRUCT lpmis;
    11.     LPDRAWITEMSTRUCT lpdis;
    12.     RECT rect;
    13.     int i;
    14.  
    15.     switch (Msg) {
    16.  
    17.         case WM_CREATE:
    18.  
    19.             // создать все дочерние окна
    20.  
    21. // непосредственно здесь производится создание Edit
    22.             g_cChat.Init();
    23.  
    24. // другая инициализация
    25. // ...
    26.  
    27.             break;
    28.  
    29.         case WM_SHOWWINDOW:
    30.  
    31.             // установить курсор
    32.             SetCursor(LoadCursor(hInst, IDC_ARROW));
    33.  
    34.             // показать окно
    35. // здесь производится установка размеров дочерних окон, в том числе и Edit
    36.             g_cChat.Show();
    37.  
    38.             break;
    39.  
    40.         case WM_GETMINMAXINFO:
    41.  
    42.             {
    43.                 // установим размеры для окна
    44.  
    45.                 MINMAXINFO * pInfo = (MINMAXINFO *) lParam;
    46.                 pInfo->ptMinTrackSize.x = g_cChat.GetMinX();
    47.                 pInfo->ptMinTrackSize.y = g_cChat.GetMinY();
    48.                 return (0);
    49.             }
    50.  
    51.         case WM_PAINT:
    52.  
    53.             dc = BeginPaint(hWnd, &ps);
    54.  
    55.             g_cChat.DrawMain(dc);
    56.  
    57.             EndPaint(hWnd, &ps);
    58.             break;
    59.  
    60.         case WM_MEASUREITEM:
    61.  
    62.             lpmis = (LPMEASUREITEMSTRUCT) lParam;
    63.  
    64.             lpmis->itemHeight = plMain.m_iListElHeight;
    65.             return (TRUE);
    66.  
    67.         case WM_DRAWITEM:
    68.  
    69.             lpdis = (LPDRAWITEMSTRUCT) lParam;
    70.  
    71.             // отрисовка элементов
    72.             plMain.ProcessDrawItem(lpdis);
    73.             g_cChat.DrawButtons(lpdis);
    74.             g_cChat.DrawTabs(lpdis);
    75.             return (TRUE);
    76.  
    77.         case WM_CONTEXTMENU:
    78.  
    79. // ...
    80.             break;
    81.  
    82.         case WM_SIZE:
    83.  
    84.             // изменить размеры + показать окно
    85.             g_cChat.Show();
    86.             break;
    87.  
    88. // Здесь идет несколько пользовательских обработчиков со значениями WM_USER + 0x400+
    89.  
    90. // ...
    91.  
    92. // обработка событий от контролов
    93.         case WM_NOTIFY:
    94.  
    95.             if (LOWORD(wParam) == IDC_CHAT_TABS) {
    96.  
    97.                 hdr = (LPNMHDR)lParam;
    98.                 if (hdr->code == NM_CLICK) {
    99.  
    100.                     // переключить на нужного пользователя
    101.                     pText = g_cChat.GetSelectedTabName();
    102.                     g_cChat.ShowView(pText);
    103.                 }
    104.             } else if (LOWORD(wParam) == IDC_DT_FROM || LOWORD(wParam) == IDC_DT_TO) {
    105.  
    106.                 // обрабатываем изменения выборки
    107.                 plMain.SetControlPos(false);
    108.                 InvalidateRect(hWnd, 0, TRUE);
    109.             }
    110.             break;
    111.  
    112.         case WM_COMMAND:
    113.  
    114. // обработчики нажатия кнопок
    115.  
    116.             return (0);
    117.  
    118.         case WM_CLOSE:
    119.  
    120.             ShowWindow(hWnd, SW_HIDE);
    121.             break;
    122.  
    123.         default:
    124.  
    125.             return (DefWindowProc(hWnd, Msg, wParam, lParam));
    126.     }
    127.  
    128.     return (0);
    129.  }
    класс окна я инициализирую так:

    Код (Text):
    1.      WNDCLASSA wc;
    2.    
    3.      SecureZeroMemory(&wc, sizeof(wc));
    4.    
    5.      wc.lpszClassName = szChatWndClassName;
    6.      wc.hInstance = hInst;
    7.      wc.lpfnWndProc = ChatWndFun;
    8.      wc.style = CS_HREDRAW | CS_VREDRAW;
    9.      wc.hCursor = LoadCursor(hInst, IDC_ARROW);
    10.      wc.hbrBackground = CreateSolidBrush(RGB(203, 203, 203));
    11.    
    12.      RegisterClassA(&wc);
    Обрабатываю очередь сообщений так:

    Код (Text):
    1.      HWND hWnd = CreateWindowExA(WS_EX_APPWINDOW,
    2.          szChatWndClassName, "", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 600, 300,
    3.          0, 0, 0, 0);
    4.  
    5.      // цикл обработки сообщений окну
    6.      MSG msg;
    7.      BOOL bRet;
    8.      while ((bRet = GetMessage(&msg, hWnd, 0, 0)) != 0) {
    9.  
    10.          if (bRet == -1) {
    11.  
    12.              DestroyWindow(hWnd);
    13.              break;
    14.          }
    15.  
    16.          TranslateMessage(&msg);
    17.          DispatchMessage(&msg);
    18.      }
     
  7. proc

    proc New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    8
    G13
    WM_INPUTLANGCHANGEREQUEST не приходит, к сожалению. Если бы он приходил, то можно было бы вручную сменить раскладку.
     
  8. proc

    proc New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    8
    Пробую перехватить функцию обработки окна Edit:
    Код (Text):
    1. LRESULT __stdcall EditWndFun(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
    2.  
    3.     if (Msg == WM_INPUTLANGCHANGEREQUEST) {
    4.  
    5.         MessageBox(hWnd, 0, 0, 0);
    6.     } else
    7.     return (CallWindowProc(g_cChat.GetOriginalEditWndProc(), hWnd, Msg,
    8.         wParam, lParam));
    9. }
    сообщение WM_INPUTLANGCHANGEREQUEST не приходит.
     
  9. maksim_

    maksim_ New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2009
    Сообщения:
    263
    proc неужто приведённый мной пример не компилится или не работает?
     
  10. proc

    proc New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    8
    maksim_
    В том-то и дело, что работает. За пример - спасибо.
    Я просто пытаюсь разобраться - с чем связаны проблемы именно в моем коде.
     
  11. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
    proc
    hWnd --> NULL ?
     
  12. proc

    proc New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    8
    kero
    Не понял сути вопроса :)
     
  13. proc

    proc New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    8
    kero
    Дошло :)
    Вы абсолютно правы, заменив hWnd на 0 добился результатов. Большой спасибо вам, а также всем, принимавшим участие в обсуждении.
    Мне нужно было внимательнее читать msdn:
    Т.е. сообщение посылается Edit'у непосредственно, а не родительскому окну.
     
  14. G13

    G13 New Member

    Публикаций:
    0
    Регистрация:
    24 мар 2006
    Сообщения:
    499
    kero
    Опередил. ;)


    proc, цитата из MSDN - правильная. Выводы - не совсем.
    Читаем внимательно описание PostMessage:
    и GetMessage: