【问题标题】:How to determine that FindText dialog is closed when user click "Cancel"当用户单击“取消”时如何确定 FindText 对话框已关闭
【发布时间】:2013-05-01 18:57:43
【问题描述】:

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

【问题讨论】:

  • 也许我错了,但是 WM_DESTROY 没有发送?

标签: c++ winapi dialog window-messages


【解决方案1】:

Read the documentation 更加小心。你采取了完全错误的方法来检测正在关闭的对话窗口。

FindText function:

在调用 FindText 之前,您必须调用 RegisterWindowMessage 函数以获取 FINDMSGSTRING 消息的标识符。当用户单击“查找下一个”按钮或对话框正在关闭时,对话框过程使用此标识符发送消息。

FINDMSGSTRING message:

当用户单击“查找下一个”、“替换”或“全部替换”按钮,或关闭对话框

...

您必须在调用 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;
}

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2018-12-02
      • 1970-01-01
      • 1970-01-01
      • 2016-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多