Этот код создает простое диалоговое окно FindText, и когда пользователь нажимает кнопку закрытия верхнего правого X-окна, сообщение WM_CLOSE отправляется в подключаемую процедуру, но при нажатии кнопки «отмена» не создается сообщение, указывающее, что окно перестало быть.
#include <windows.h>
#include <iostream>
#include <iomanip>
UINT_PTR CALLBACK FRHookProc(HWND hdlg, UINT uiMsg, WPARAM /*wParam*/, LPARAM /*lParam*/) {
switch (uiMsg) {
case WM_INITDIALOG: {
ShowWindow(hdlg, SW_SHOW);
break;
}
}
using namespace std;
if (uiMsg == WM_CLOSE) cout << "FindTextW window has been closed";
return 0;
}
LRESULT CALLBACK MyWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
return DefWindowProcW(hWnd, Msg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR, int /* nCmdShow*/) {
using namespace std;
WNDCLASSEXW wc;
wc.cbSize = sizeof(WNDCLASSEXW);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = &MyWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(PVOID);
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hIconSm = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_BACKGROUND);
wc.lpszMenuName = L"MainMenu";
wc.lpszClassName = L"window";
ATOM class_atom = RegisterClassExW(&wc);
HWND hWnd = CreateWindowExW(
0,
reinterpret_cast<LPCWSTR>(class_atom),
L"window title",
WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPCHILDREN | WS_THICKFRAME,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
WCHAR szFindWhat[MAX_PATH] = {0};
FINDREPLACEW fr;
ZeroMemory(&fr, sizeof(fr));
fr.lStructSize = sizeof(fr);
fr.hwndOwner = hWnd;
fr.lpstrFindWhat = szFindWhat;
fr.lpfnHook = FRHookProc;
fr.wFindWhatLen = MAX_PATH;
fr.Flags = FR_ENABLEHOOK;
/*HWND hdlg =*/ FindTextW(&fr);
MSG msg;
for (;;) {
GetMessageW(&msg, 0, 0, 0);
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return 0;
}
Читать документацию более осторожно Вы приняли совершенно неправильный подход к обнаружению закрытия диалогового окна.
Перед вызовом FindText вы должен вызвать функцию RegisterWindowMessage получить идентификатор для сообщения FINDMSGSTRING. Процедура диалогового окна использует этот идентификатор для отправки сообщений, когда пользователь нажимает кнопку «Найти далее», или когда диалоговое окно закрывается.
Диалоговое окно «Найти или заменить» отправляет зарегистрированное сообщение FINDMSGSTRING к процедуре окна своего владельца окна когда пользователь нажимает кнопку «Найти далее», «Заменить» или «Заменить все» или закрывает диалоговое окно.
…
Вы должны указать константу FINDMSGSTRING в вызове функции RegisterWindowMessage, чтобы получить идентификатор сообщения, отправленного диалоговым окном.
При создании диалогового окна используйте член hwndOwner структуры FINDREPLACE, чтобы определить окно для получения сообщений FINDMSGSTRING..
…
Член Flags структуры FINDREPLACE включает в себя один из следующих флагов, чтобы указать событие, которое вызвало сообщение.
FR_DIALOGTERM (0x00000040)
Диалоговое окно закрывается. После того, как окно владельца обработает это сообщение, дескриптор диалогового окна больше не действителен.
Итак, с этим сказал, попробуйте это вместо:
#include <windows.h>
#include <iostream>
#include <iomanip>
static const UINT uFindMsgString = RegisterWindowMessageW(L"commdlg_FindReplace");
LRESULT CALLBACK MyWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
if ((Msg == uFindMsgString) && (Msg != 0))
{
FINDREPLACE *fr = reinterpret_cast<FINDREPLACE*>(lParam);
if (fr->flags & FR_DIALOGTERM)
{
std::cout << "FindTextW window has been closed";
PostQuitMessage(0);
}
// process other dialog notifications as needed...
return 0;
}
return DefWindowProcW(hWnd, Msg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR, int /* nCmdShow*/)
{
WNDCLASSEXW wc = {0};
wc.cbSize = sizeof(WNDCLASSEXW);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = &MyWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(PVOID);
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hIconSm = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_BACKGROUND);
wc.lpszMenuName = L"MainMenu";
wc.lpszClassName = L"window";
ATOM class_atom = RegisterClassExW(&wc);
HWND hWnd = CreateWindowExW(
0,
wc.lpszClassName,
L"window title",
WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPCHILDREN | WS_THICKFRAME,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
WCHAR szFindWhat[MAX_PATH] = {0};
FINDREPLACEW fr = {0};
fr.lStructSize = sizeof(fr);
fr.hwndOwner = hWnd;
fr.lpstrFindWhat = szFindWhat;
fr.wFindWhatLen = MAX_PATH;
HWND hdlg = FindTextW(&fr);
MSG msg;
while (GetMessageW(&msg, 0, 0, 0) > 0)
{
if (!IsDialogMessage(hdlg, &msg))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
DestroyWindow(hWnd);
UnregisterClass(wc.lpszClassName, hInstance);
return 0;
}
Вы должны получить WM_COMMAND
уведомление для кнопки отмены BN_CLICKED
сообщение. При нажатии «отмена» вы должны получить это уведомление для ID элемента управления IDCANCEL.