win32 SetFocus问题

无忧老猪 2013-08-19 08:45:47
我在用win32 api写程序。
程序是单线程的,即只有WinMain函数这一个主线程。
我遇到的问题抽象描述如下:
程序的主窗口(即frame窗口)中,有两个子窗口A和B。
A中有一个子窗口C,他是一个标准的edit控件。
B中有一个子窗口D,他是我自己实现的一个窗口,功能类似于edit。
我在D窗口的WM_LBUTTONDOWN消息处理中,调用SetFocus,使得D能够响应键盘输入。
本来这一切都是正常的。
但问题是,如果鼠标点击一下窗口C的内部,使得C获得Focus。
然后,再点击窗口D的内部,无论如何点击,D都无法获得Focus了。
SetFocus(hwnd)之后, GetLastError返回值为5。

我已经检查了我调用SetFocus(hwnd)时传入的窗口句柄,句柄是完全正确的。
...全文
438 7 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
无忧老猪 2013-08-22
  • 打赏
  • 举报
回复
gfm688,你太牛了:)
gfm688 2013-08-22
  • 打赏
  • 举报
回复
其实点击窗口D的内部,D已经Focus了,估计是Caret在那个标准的edit控件KillFocus时被Destroy了,所以没法显示出来,正确的做法是:

  case   WM_SETFOCUS:
  {
    CreateCaret(hwnd, NULL, 1, cyChar);
    SetCaretPos(cur_data_len*cxChar, 0);
    ShowCaret(hwnd);
    return 0 ;
  }

  case   WM_KILLFOCUS:
  {
   HideCaret(hwnd);
   DestroyCaret();
   return 0 ;
  }
  case WM_LBUTTONDOWN:
  {
    SetFocus(hwnd);
    return 0;
  }
无忧老猪 2013-08-21
  • 打赏
  • 举报
回复
我把程序简化了一下,问题有点变化,但还是不正常。
只要点击一下frame上面的那个edit控件,我自己的窗口就无法获得光标了。

#include <windows.h>
#include <commctrl.h>

#define FAIL (-1)
#define SUCCESS (0)

HINSTANCE g_hInstance;
TCHAR szAppName[] = TEXT ("demo_app") ;


HWND hwnd_frame, hwnd_my_edit, hwnd_edit;

TCHAR szMyEditWinClassName[] = TEXT ("my_edit") ;
TEXTMETRIC textmetric;
int cxChar;
int cyChar;

char test_buf[2048] = "hello";

int cur_data_len=5;

LRESULT CALLBACK my_edit_WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc ;
PAINTSTRUCT ps ;

switch (message)
{
case WM_CREATE:

hdc = CreateIC (TEXT("DISPLAY"), NULL, NULL, NULL) ;
SelectObject (hdc, GetStockObject(SYSTEM_FIXED_FONT)) ;
GetTextMetrics(hdc, &textmetric) ;
DeleteObject (SelectObject (hdc, GetStockObject(SYSTEM_FONT))) ;
DeleteDC (hdc) ;

cxChar = textmetric.tmAveCharWidth ;
cyChar = textmetric.tmHeight + textmetric.tmExternalLeading ;

CreateCaret(hwnd, NULL, cxChar, cyChar);

return 0 ;


case WM_PAINT :
hdc = BeginPaint (hwnd, &ps) ;
SelectObject (hdc, GetStockObject(SYSTEM_FIXED_FONT)) ;

TextOutA(hdc, 0, 0, test_buf, cur_data_len) ;

DeleteObject (SelectObject (hdc, GetStockObject(SYSTEM_FONT))) ;
EndPaint (hwnd, &ps) ;
return 0 ;

case WM_CHAR:
{
test_buf[cur_data_len]=wParam;
cur_data_len++;

SetCaretPos(cur_data_len*cxChar, 0);
InvalidateRect (hwnd, NULL, TRUE) ;
return 0 ;
}

case WM_SETFOCUS:
{
ShowCaret(hwnd);
return 0 ;
}

case WM_KILLFOCUS:
{
HideCaret(hwnd);
return 0 ;
}
case WM_LBUTTONDOWN:
{
SetFocus(hwnd);
SetCaretPos(cur_data_len*cxChar, 0);
ShowCaret(hwnd);
return 0;

}
}

return DefWindowProc (hwnd, message, wParam, lParam) ;
}

int register_my_edit_win()
{
WNDCLASS sub_wndclass;
sub_wndclass.style = CS_HREDRAW | CS_VREDRAW| CS_DBLCLKS;
sub_wndclass.lpfnWndProc= my_edit_WndProc;
sub_wndclass.cbClsExtra = 0;
sub_wndclass.cbWndExtra = 0;
sub_wndclass.hInstance = g_hInstance;
sub_wndclass.hIcon = LoadIcon (g_hInstance, IDI_APPLICATION);
sub_wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
sub_wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
sub_wndclass.lpszMenuName = NULL;
sub_wndclass.lpszClassName = szMyEditWinClassName;


if (!RegisterClass (&sub_wndclass))
{
MessageBox (NULL, TEXT ("Program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return FAIL;
}

return SUCCESS;

}

int reg_sys_win_classes()
{
INITCOMMONCONTROLSEX icex; // Structure for control initialization.
icex.dwSize = sizeof(icex);
icex.dwICC = ICC_STANDARD_CLASSES|ICC_BAR_CLASSES|ICC_TAB_CLASSES
|ICC_TREEVIEW_CLASSES|ICC_LISTVIEW_CLASSES;

InitCommonControlsEx(&icex);

}

TCHAR szFrameWinClassName[] = TEXT ("my_frame") ;
HWND hwnd_frame;

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
hwnd_edit = CreateWindow (TEXT("edit"), TEXT ("haha"),
WS_CHILD | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
hwnd, NULL, g_hInstance, NULL) ;

hwnd_my_edit = CreateWindow (szMyEditWinClassName, NULL,
WS_CHILD | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
hwnd, NULL, g_hInstance, NULL) ;
return 0 ;


case WM_SIZE:
MoveWindow(hwnd_edit, 0, 10, 100, 20, TRUE) ;
MoveWindow(hwnd_my_edit,0, 40, 600, 200, TRUE) ;
return 0 ;


case WM_CLOSE:
DestroyWindow (hwnd) ;
return 0 ;

case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}

int register_frame()
{
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc= WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = g_hInstance;
wndclass.hIcon = LoadIcon (g_hInstance, IDI_APPLICATION);
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szFrameWinClassName;

if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("Program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return FAIL;
}

return SUCCESS;

}

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{

MSG msg ;
HACCEL hAccel ;

g_hInstance = hInstance;

reg_sys_win_classes();
register_frame();
register_my_edit_win();

hwnd_frame = CreateWindow (szFrameWinClassName, szAppName,
WS_OVERLAPPEDWINDOW|WS_MAXIMIZE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, g_hInstance, NULL) ;

ShowWindow (hwnd_frame, SW_MAXIMIZE) ;
UpdateWindow (hwnd_frame) ;
;

while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}

return msg.wParam ;
}


Eleven 2013-08-21
  • 打赏
  • 举报
回复
你的代码里是怎么写的?
davidyu720 2013-08-21
  • 打赏
  • 举报
回复
贴一下代码。 或者参考http://stackoverflow.com/questions/9643536/setfocus-fails-with-a-valid-window-handle
fishion 2013-08-21
  • 打赏
  • 举报
回复
在D窗口中点击了就不需要调用SetFocus了
无忧老猪 2013-08-20
  • 打赏
  • 举报
回复
晕倒。在下的问题无人问津啊。

15,980

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧