1

此代码生成简单的 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;
}
4

2 回答 2

2

更仔细地阅读文档。您采取了完全错误的方法来检测正在关闭的对话窗口。

查找文本功能

在调用 FindText 之前,您必须调用 RegisterWindowMessage 函数来获取 FINDMSGSTRING 消息的标识符。当用户单击 Find Next 按钮或对话框正在关闭时,对话框过程使用此标识符发送消息。

FINDMSGSTRING 消息

当用户单击“查找下一个”、“替换”或“全部替换”按钮或关闭对话框时,查找或替换对话框将 FINDMSGSTRING 注册消息发送到其所有者窗口的窗口过程

...

您必须在对 RegisterWindowMessage 函数的调用中指定 FINDMSGSTRING 常量,以获取对话框发送的消息的标识符。

创建对话框时,使用 FINDREPLACE 结构的 hwndOwner 成员来标识要接收 FINDMSGSTRING 消息的窗口

...

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;
}
于 2013-05-02T01:34:52.057 回答
0

您应该会收到WM_COMMAND取消按钮BN_CLICKED消息的通知。当按下“取消”时,您应该会收到 IDCANCEL 控件 ID 的通知。

于 2013-05-01T20:07:10.790 回答