DS_CONTROL | Комбинация WS_CHILD вызывает бесконечный цикл
Привет.
Я пытаюсь создать пример "диалогового окна в диалоге" с использованием WinAPI и C. Этот пример состоит из дочернего диалога с автоматической галочкой и главного диалогового окна, содержащего статический черный прямоугольник, который является родительским для дочернего диалога, и push кнопка, которая показывает в окне сообщения текст со статусом флажка.
Когда я устанавливаю флаги DS_CONTROL | WS_CHILD
для дочернего диалога всякий раз, когда я пытаюсь изменить статус флажка, приложение входит в бесконечный цикл, и мне приходится принудительно закрывать его. Когда я удаляю DS_CONTROL
флаг, работает как задумано, но я не могу переключаться между элементами управления с помощью клавиши табуляции.
Что я могу сделать, чтобы заставить его работать как задумано, используя DS_CONTROL
флаг?
Вот содержание моего main.c
файл:
#include <windows.h>
#pragma comment (lib, "user32")
HINSTANCE hInst;
BOOL isChecked;
const unsigned char checkedStr[] = "Checkbox is checked";
const unsigned char notCheckedStr[] = "Checkbox is not checked";
BOOL CALLBACK ChildDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_COMMAND:
switch (LOWORD(wParam))
{
case 21:
isChecked = IsDlgButtonChecked(hwndDlg, 21);
return TRUE;
}
return FALSE;
}
return FALSE;
}
BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_INITDIALOG:
{
HWND hContainer, hChilddDlg;
hContainer = GetDlgItem(hwndDlg, 11);
hChilddDlg = CreateDialogParam(hInst, MAKEINTRESOURCE(20), hContainer, ChildDlgProc, 0);
ShowWindow(hChilddDlg, SW_SHOW);
return TRUE;
}
case WM_COMMAND:
switch (LOWORD(wParam))
{
case 12:
{
const unsigned char *ptr;
if (isChecked)
{
ptr = checkedStr;
}
else
{
ptr = notCheckedStr;
}
MessageBox(hwndDlg, ptr, TEXT("Checkbox status"), MB_OK | MB_ICONINFORMATION);
return TRUE;
}
}
return FALSE;
case WM_CLOSE:
EndDialog(hwndDlg, 0);
return TRUE;
}
return FALSE;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
hInst = hInstance;
isChecked = FALSE;
return DialogBoxParam(hInstance, MAKEINTRESOURCE(10), NULL, DialogProc, 0);
}
А вот и содержание моего rsrc.rc
файл:
#include <windows.h>
10 DIALOGEX 0, 0, 130, 47
STYLE DS_CENTER | DS_SETFONT | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU
CAPTION "Checkbox status"
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
FONT 9, "Segoe UI"
{
CONTROL "", 11, STATIC, SS_BLACKRECT | WS_CHILD | WS_VISIBLE, 5, 5, 120, 20
CONTROL "&Status", 12, BUTTON, BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 75, 30, 50, 12
}
20 DIALOGEX 0, 0, 120, 20
STYLE DS_SETFONT | DS_CONTROL | WS_CHILD
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
FONT 9, "Segoe UI"
{
CONTROL "Checkbox", 21, BUTTON, BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0, 5, 50, 10
}
Я компилирую его в командной строке Visual C++ с помощью: cl /c main.c && rc rsrc.rc && link /SUBSYSTEM:WINDOWS /OUT:test.exe main.obj rsrc.res
,
Заранее спасибо за помощь.
1 ответ
Нашел решение в исходном коде NSIS. Проблема заключалась в том, что я помещал дочерний диалог как дочерний элемент blackrect, чтобы он был вне цикла событий основного диалога, вызывая зависание. Чтобы решить эту проблему, я должен был поставить его как дочерний элемент основного диалога и переместить его через черную линию.
Вот обновленный код WM_INITDIALOG
case в главном диалоге proc:
// ...
case WM_INITDIALOG:
{
HWND hChilddDlg;
hChilddDlg = CreateDialogParam(hInst, MAKEINTRESOURCE(20), hwndDlg, ChildDlgProc, 0);
if (hChilddDlg)
{
RECT rect;
GetWindowRect(GetDlgItem(hwndDlg, 11), &rect);
ScreenToClient(hwndDlg, (LPPOINT)&rect);
SetWindowPos(hChilddDlg, 0, rect.left, rect.top, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
ShowWindow(hChilddDlg, SW_SHOWNA);
}
return TRUE;
}
// ...
С этим я смог использовать DS_CONTROL
флаг и табуляция между элементами управления.