winapi C++;处理焦点 我正在研究一个C++ WiNAPI应用程序,我正在努力让 StFixCube()/Cuth>为我工作。我使用WS|u OVERLAPPEDWINDOW | WS|u VISIBLE创建主窗口,然后在其中使用WS|u CHILD | WS|u VISIBLE创建它的子窗口(几个按钮和我自己版本的编辑控件的开头),这些子窗口除了焦点问题之外都可以正常工作
在我的搜索中,我一直在努力寻找更多关于如何处理焦点的信息。当所有窗口都被创建时,它们分别收到winapi C++;处理焦点 我正在研究一个C++ WiNAPI应用程序,我正在努力让 StFixCube()/Cuth>为我工作。我使用WS|u OVERLAPPEDWINDOW | WS|u VISIBLE创建主窗口,然后在其中使用WS|u CHILD | WS|u VISIBLE创建它的子窗口(几个按钮和我自己版本的编辑控件的开头),这些子窗口除了焦点问题之外都可以正常工作,c++,winapi,setfocus,wndproc,C++,Winapi,Setfocus,Wndproc,在我的搜索中,我一直在努力寻找更多关于如何处理焦点的信息。当所有窗口都被创建时,它们分别收到WM_SETFOCUS消息,我在编辑控件中通过添加插入符号来处理此消息,但是孩子们似乎从未收到WM_KILLFOCUS消息,因此插入符号从未被销毁 这就是我的问题所在:我希望主父窗口最初有焦点,并且在我的编辑控件中没有插入符号,然后当单击子编辑控件时,它有焦点,然后当单击主窗口时,它应该再次有焦点,依此类推 因此,我最初的想法是在处理WM\u CREATE消息时使用SetFocus()将焦点设置到主窗口,
WM_SETFOCUS
消息,我在编辑控件中通过添加插入符号来处理此消息,但是孩子们似乎从未收到WM_KILLFOCUS
消息,因此插入符号从未被销毁
这就是我的问题所在:我希望主父窗口最初有焦点,并且在我的编辑控件中没有插入符号,然后当单击子编辑控件时,它有焦点,然后当单击主窗口时,它应该再次有焦点,依此类推
因此,我最初的想法是在处理WM\u CREATE
消息时使用SetFocus()
将焦点设置到主窗口,但这似乎不起作用:孩子没有收到WM\u KILLFOCUS
消息
我的下一个想法是,也许家长必须处理将WM_KILLFOCUS传递给适当的孩子的问题,所以我为我写了一个方法,但孩子们仍然没有收到WM_KILLFOCUS
消息
因此,我最好的猜测是我在WndProc中没有正确处理消息
我已经创建了自己的窗口类,并通过以下WndProc将消息分发到相应的类:
LRESULT CALLBACK CBaseWindow::stWinMsgHandler(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
CBaseWindow* pWnd;
if (uMsg == WM_NCCREATE)
{
SetWindowLong(hwnd, GWL_USERDATA, (long)((LPCREATESTRUCT(lParam))->lpCreateParams));
}
pWnd = GetObjectFromWindow(hwnd);
if (pWnd)
return pWnd->WinMsgHandler(hwnd, uMsg, wParam, lParam);
else
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
然后每个类都有自己的WndProc,我在其中处理传入的消息
有人对我有什么想法吗
如果我这样做是完全错误的,或者如果我没有遵循最佳实践,请说出来,我这样做是为了学习,所以就开枪吧
[更新]
好的,下面是一些代码来演示问题:
Main.cpp
MainWnd.cpp
CustomTextBox.cpp
发现
在编写这段代码的过程中,我遇到了问题的原因之一:在我的实际应用程序中,我没有标题栏,因此要将我发送的窗口WM\u nbuttondown
移动到我的主窗口WM\u LBUTTONDOWN
:
SendMessage(hwnd,WM\nclubuttondown,HTCAPTION,NULL)代码>
然后,我的SetFocus()
在这之后就不起作用了,但是如果我先切换它们并处理SetFocus()
,那么单击会改变焦点
不过,初始设置焦点仍然存在问题。启动应用程序后,自定义编辑控件仍会显示插入符号,即使它没有焦点,您需要单击它以使其具有焦点,从而它将接收键盘输入。在此之后,焦点按预期工作:如果我点击主窗口,它就有焦点;如果我点击自定义编辑,它会有焦点等。确定,所以我的整个问题都在于那行发送消息(hwnd,WM\nclubuttondown,HTCAPTION,NULL)代码>一旦我切换这个:
case WM_LBUTTONDOWN:
SendMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, NULL);
SetFocus(hwnd);
break;
致:
一切都在一起。请发布一个完整的示例来演示这个问题。WM_KILLFOCUS总是在窗口即将失去焦点时发送到窗口。因此,您的代码中可能有错误。另一件事-您是否尝试将WS_TABSTOP样式添加到子窗口?尝试从测试应用程序中删除所有特定于焦点的(添加的)代码,并查看默认情况下焦点是如何工作的。如果它能工作,那么你似乎做了一些过度的事情,要么阻碍正常的聚焦处理,要么连续做两次——也就是说,你聚焦的只是非聚焦控制,反之亦然。如果不起作用,则您以错误的方式创建了父窗口或控件。@aleguna我发布了描述我的问题的代码,并向子窗口添加了WS_TABSTOP
,但它仍然不能完全起作用@Stan我试图删除所有特定于焦点的代码,但仍然无法正常工作。如果你阅读我上面的更新,你会看到我几乎所有的代码。希望我们能找出我的错误所在。谢谢你的帮助OK我已经解决了移动窗口和关注点击的问题。只是现在开始设定焦点才是一个问题。
#include "BaseWindow.h"
//...
LRESULT CALLBACK CBaseWindow::stWinMsgHandler(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
CBaseWindow* pWnd;
if (uMsg == WM_NCCREATE)
{
SetWindowLong(hwnd,
GWL_USERDATA,
(long)((LPCREATESTRUCT(lParam))->lpCreateParams));
}
pWnd = GetObjectFromWindow(hwnd);
if (pWnd)
return pWnd->WinMsgHandler(hwnd, uMsg, wParam, lParam);
else
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
BOOL CBaseWindow::Create(DWORD dwStyles, RECT* rect)
{
m_hwnd = CreateWindow(
szClassName,
szWindowTitle,
dwStyles,
rect->left,
rect->top,
rect->right - rect->left,
rect->bottom - rect->top,
NULL,
NULL,
hInstance,
(void *)this);
return (m_hwnd != NULL);
}
#include "MainWnd.h"
#define WIDTH 400
#define HEIGHT 400
MainWnd::MainWnd(HINSTANCE hInst): CBaseWindow(hInst), hInstance(hInst)
{
SetWindowTitle(_T("Main Window"));
WNDCLASSEX wcx;
FillWindowClass(&wcx);
if(RegisterWindow(&wcx))
{
RECT rc;
BuildRect(&rc);
if(Create(WS_OVERLAPPEDWINDOW | WS_VISIBLE, &rc))
{
customTextBox = new CustomTextBox(hInst, m_hwnd);
}
}
}
void MainWnd::FillWindowClass(WNDCLASSEX *wcx)
{
wcx->cbSize = sizeof(WNDCLASSEX);
wcx->style = CS_HREDRAW | CS_VREDRAW | CS_DROPSHADOW;
wcx->lpfnWndProc = CBaseWindow::stWinMsgHandler;
wcx->cbClsExtra = 0;
wcx->cbWndExtra = 0;
wcx->hInstance = hInstance;
wcx->hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcx->hCursor = LoadCursor(NULL, IDC_ARROW);
wcx->hbrBackground = CreateSolidBrush(RGB(255,255,255));
wcx->lpszMenuName = NULL;
wcx->lpszClassName = _T("MainWindow");
wcx->hIconSm = LoadIcon(NULL, IDI_APPLICATION);
}
LRESULT CALLBACK MainWnd::WinMsgHandler(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
delete customTextBox;
PostQuitMessage(0);
break;
case WM_LBUTTONUP:
SetFocus(hwnd);
break;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
#include "CustomTextBox.h"
CustomTextBox::CustomTextBox(
HINSTANCE hInst,
HWND hParent): CBaseWindow(hInst),
hParent(hParent),
{
WNDCLASSEX wcx;
CreateWndClassEX(wcx);
if(RegisterWindow(&wcx))
{
RECT clientRect;
CreateClientRect(clientRect);
CreateChild(WS_VISIBLE | WS_CHILD | WS_BORDER | WS_TABSTOP, &clientRect, hParent);
}
}
void CustomTextBox::CreateWndClassEX(WNDCLASSEX& wcx)
{
wcx.cbSize = sizeof(WNDCLASSEX);
wcx.style = CS_HREDRAW | CS_VREDRAW;
wcx.lpfnWndProc = CBaseWindow::stWinMsgHandler;
wcx.cbClsExtra = 0;
wcx.cbWndExtra = 0;
wcx.hInstance = hInstance;
wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
wcx.hbrBackground = CreateSolidBrush(RGB(255,255,255));
wcx.lpszMenuName = NULL;
wcx.lpszClassName = _T("Edit Control");
wcx.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
}
LRESULT CALLBACK CustomTextBox::WinMsgHandler(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
switch(uMsg)
{
/* Handling the caret */
case WM_SETFOCUS:
CreateCaret(hwnd, NULL, 0, nWindowY);
SetCaretPos(GetEndOfLinePoint(), nCaretPosY * nCharY);
ShowCaret(hwnd);
return 0;
case WM_MOUSEACTIVATE:
SetFocus(hwnd);
return MA_ACTIVATE;
case WM_KILLFOCUS:
DestroyCaret();
return 0;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
case WM_LBUTTONDOWN:
SendMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, NULL);
SetFocus(hwnd);
break;
case WM_LBUTTONDOWN:
SetFocus(hwnd);
SendMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, NULL);
break;