我在主函数中创建了一个主窗口。在WM_CREATE消息的主窗口过程中,我使用系统“编辑”窗口类创建了一个编辑控件,它作为父窗口的子窗口。我希望在编辑控件中按下回车键时将焦点转移到主窗口。因为我使用了系统类,所以我无权访问它的过程。我在 Visual Studio 10 中为此使用C++因为我是 win32 应用程序的新手,所以无论代码有多长,我都想要一个简单的解决方案
1 回答
如果您的窗口只有一个可聚焦控件(例如编辑控件),则该控件将始终具有焦点。你不能有一个没有焦点控件的窗口,并且父窗口本身是不可聚焦的(即不能有焦点)。
因此,如果您还没有,您首先需要向窗口添加另一个可聚焦控件(我无法从问题中看出)。例如,您可以添加“确定”或“取消”按钮。这样,每当您取消编辑控件的焦点时,按钮都可以接收焦点。
然后,您将需要对编辑控件进行子类化,以便您可以处理其按键事件(例如WM_KEYDOWN
和WM_KEYUP
)。要子类化单个窗口,请调用该SetWindowLongPtr
函数并将窗口句柄与GWLP_WNDPROC
标志和指向自定义窗口过程的指针一起传递。这有效地用您的自定义窗口过程替换了该类控件的默认窗口过程。例如:
// Stores the old original window procedure for the edit control.
WNDPROC wpOldEditProc;
// The new custom window procedure for the edit control.
LRESULT CALLBACK CustomEditProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_KEYDOWN:
{
if (wParam == VK_RETURN)
{
// The user pressed Enter, so set the focus to the other control
// on the window (where 'hwndOther' is a handle to that window).
SetFocus(hwndOther);
// Indicate that we processed the message.
return 0;
}
}
}
// Pass the messages we don't process here on to the
// original window procedure for default handling.
CallWindowProc(wpOldEditProc, hWnd, msg, wParam, lParam);
}
// ----- Add to the parent window's WM_CREATE: -----
// Create the edit control
HWND hwndEdit = CreateWindowEx(...);
// Subclass it.
wpOldEditProc = (WNDPROC)SetWindowLongPtr(hwndEdit,
GWLP_WNDPROC,
(LONG_PTR)CustomEditProc);
// Show it.
ShowWindow(hwndEdit, SW_SHOW);
// ... your other code (e.g. creating and showing the other control)
// ----- Add to the parent window's WM_DESTROY: -----
// Unsubclass the edit control.
SetWindowLongPtr(hwndEdit, GWLP_WNDPROC, (LONG_PTR)wpOldEditProc);
// ... your other code (e.g. calling PostQuitMessage(...) to close your app)
MSDN 上有关子类化窗口的进一步阅读。那里的示例代码(以及 Web 上的许多其他地方)假定您正在对对话框窗口中的编辑控件进行子类化。因为对话框是自动处理大量键盘处理的特殊类型的父窗口,所以您需要采取额外的步骤来克服对话框完成的这种默认处理。如果您使用的是使用 创建的常规窗口CreateWindowEx
,则没有必要。
如果您想要多个编辑控件在响应某些按键时都以相同的方式运行,那么注册自定义窗口子类会更加简洁和更好的设计。鉴于上述代码仅对单个编辑控件对象进行子类化,这种方法将创建一种新类型的自定义编辑控件类。您可以根据需要创建尽可能多的这种新型编辑控件的实例,并且它们的行为方式都相同。
但我不会在这里讨论如何做到这一点。如果您有兴趣,可以在网上找到代码,而您的特定用例会使它变得更复杂一些。为了改变焦点,控件必须知道它应该将焦点设置到哪个其他控件。这很难在全球范围内处理。建议使用对话窗口作为父窗口。它管理 Z 顺序并自动为您设置焦点。