为什么控件window显示不出来?
Why the window of control coulnd't appear?
在微软网站上看到一篇文章MSDN介绍了一种高级的写法
我把它应用到class的扩展中,通常我没有问题。
但是最近在尝试写一个class的时候遇到了问题。
我想实现一个listview class 方便我们操作listview控件的时候
template <class DERIVED_TYPE>
class BaseWindow
{
public:
LPCTSTR className = "myWindows";
LPCTSTR Caption = "myWindows";
DWORD Style = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
UINT classStyle = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
DWORD ExStyle = 0;
...
other_property
...
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
DERIVED_TYPE *pThis = NULL;
if (uMsg == WM_NCCREATE)
{
CREATESTRUCT* pCreate = (CREATESTRUCT*)lParam;
pThis = (DERIVED_TYPE*)pCreate->lpCreateParams;
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis);
if (pThis)pThis->m_hwnd = hwnd;
}else{
pThis = (DERIVED_TYPE*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
if(pThis)pThis->m_hwnd = hwnd;
}
if (pThis)
{
return pThis->HandleMessage(hwnd, uMsg, wParam, lParam);
}else{
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
ATOM RegClass()
{
WNDCLASS wc = { 0 };
wc.lpfnWndProc = BaseWindow::WindowProc;
wc.hInstance = hInst;
wc.lpszClassName = className;
wc.style = classStyle;
wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
return RegisterClass(&wc);
}
BOOL CreateWinEx( LPCTSTR className_,LPCTSTR Caption_,
DWORD Style_,DWORD ExStyle_,
int x_,int y_,int w_,int h_,
HWND hWndParent_,HMENU hMenu_,HINSTANCE hInst_)
{
m_hwnd = CreateWindowEx(
ExStyle_, className_, Caption_, Style_,
x_, y_, w_, h_,
hWndParent_, hMenu_, hInst_, this
);
return (m_hwnd ? TRUE : FALSE);
}
BOOL Create()
{
ATOM rst = RegClass();
if(rst == 0) return FALSE;
m_hwnd = CreateWindowEx(
ExStyle, className, Caption, Style,
x, y, w, h,
hWndParent, hMenu, hInst, this
);
return (m_hwnd ? TRUE : FALSE);
}
}
基于以上,我导出了两个class,一个作为主窗体,一个作为我要设计的listviewclass
class FirstWindow : public BaseWindow<FirstWindow>
{
public:
FirstWindow(){};
...
some_property
...
LRESULT HandleMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK ButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
public:
};
class listView : public BaseWindow<listView>
{
public:
listView();
int init(LPCTSTR className_,HWND hWndParent_,int x,int y,int w,int h)
{
this->className = className_;
this->hWndParent = hWndParent_;
this->Style = WS_CHILD| WS_VISIBLE | ~WS_CAPTION;
this->x = x;
this->y = y;
this->w = w;
this->h = h;
this->Create();
hWndMsgWindow = m_hwnd;
CreateListView(hWndMsgWindow);
ShowWindow(hWndMsgWindow,SW_SHOW);
ShowWindow(hWndListView,SW_SHOW);
UpdateWindow(hWndMsgWindow);
UpdateWindow(hWndListView);
idebug("listview::init >> hWndMsgWindow:%d,parent:%d, error:%d\n",hWndMsgWindow,GetParent(hWndMsgWindow), GetLastError());
idebug("listview::init >> hWndListView:%d,parent:%d,error:%d\n",hWndListView,GetParent(hWndListView), GetLastError());
return 1;
}
LRESULT HandleMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT listView::CreateListView(HWND hwndParent_)
{
InitCommonControls();
bool rst = CreateWinEx(WC_LISTVIEW, NULL,
WS_CHILD | WS_VISIBLE | LVS_REPORT |LVS_EDITLABELS | LVS_NOCOLUMNHEADER | LVS_OWNERDATA |LVS_OWNERDRAWFIXED | WS_BORDER,0,
x,y,w,h,
hwndParent_, NULL, GetModuleHandle(NULL));
if(rst)
hWndListView = m_hwnd;
idebug("CreateListView >> rst:%d,hwndlistview:%d,parent:%d,hwndParent_:%d, error:%d\n",rst,hWndListView,GetParent(hWndListView),hwndParent_, GetLastError());
return rst;
}
LRESULT AddItem();
LRESULT OnListViewNotify(HWND hwnd, LPARAM lParam);
void OwnerDraw(LPDRAWITEMSTRUCT lpdis, HDC hdc, HWND hWnd, const TCHAR* szDraw);
void on_drawItem(HWND hWnd, LPARAM lParwm);
void on_notify(HWND hWnd, WPARAM wParwm, LPARAM lParam);
void on_create(HWND hWnd);
void on_measureItem(LPARAM lParam);
bool add_item();
bool add_item_sub();
...
some_property
...
};
首先触发 FirstWindow
FirstWindow * pFirstWnd;
listView lv;
int main(int argc, char** argv)
{
FirstWindow win;
pFirstWnd = &win;
win.className = "FirstWindow";
win.Style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
win.x = 100;
win.y = 100;
win.w = 600;
win.h = 300;
bool rst = win.Create();
if (!rst)
{
idebug("getlasterror:%d,line:201\n", GetLastError());
bug.ShowErr();
}
else {
lv.init("mylistview",pFirstWnd->m_hwnd,20,20,300,200);
ShowWindow(lv.m_hwnd, SW_SHOW);
}
MSG msg = {};
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
listview_class 的目标是能够独立接收和处理 window 消息。 不是这样的:
LRESULT FirstWindow::HandleMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE:
{
//lv.init("mylistview2",pFirstWnd->m_hwnd,20,20,300,200);
//ShowWindow(lv.m_hwnd, SW_SHOW);
break;
}
case WM_NOTIFY:
{
lv.on_notify(hWnd,wParam,lParam);
break;
}
...
}
default:
return DefWindowProc(m_hwnd, uMsg, wParam, lParam);
}
return TRUE;
}
相反,我想在列表视图中独立处理消息class,像这样:
LRESULT listView::HandleMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
static HDC hdc;
HRESULT lResult;
switch (uMsg)
{
case WM_CREATE:
{
idebug("class_listview >> WM_CREATE >> hWnd :%d, className:%s, parent:%d\n",hWnd, className , GetParent(hWnd));
//HWND h = CreateWindowEx(0, WC_LISTVIEW, NULL,
WS_CHILD | WS_VISIBLE | LVS_REPORT |LVS_EDITLABELS | LVS_NOCOLUMNHEADER | LVS_OWNERDATA |LVS_OWNERDRAWFIXED | WS_BORDER,
20,20,300,200,
hWnd,NULL, GetModuleHandle(NULL),NULL);
//ShowWindow(h,SW_SHOW);
//UpdateWindow(hWnd);
//idebug("class_listview >> WM_CREATE >> hwnd:%d,parent:%d,error:%d\n",h,GetParent(h), GetLastError());
//ShowWindow(h,SW_SHOW);
//UpdateWindow(h);
break;
}
case WM_NOTIFY:
{
on_notify(hWnd,wParam,lParam);
break;
}
case WM_MEASUREITEM:
{
on_measureItem(lParam);
break;
}
case WM_DRAWITEM:
{
on_drawItem(hWnd,lParam);
break;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 2));
EndPaint(hWnd, &ps);
idebug("class_listview >> WM_PAINT->hWnd:%d,id:%d,err:%d\n", hWnd, id, GetLastError());
break;
}
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
现在的问题是除了FirstWindow可以正常显示外,我看不到其他控件windows
更新:
来自调试的一些消息:
class_listview >> WM_CREATE >> hWnd :1443146, className:mylistview, parent:262350,error:0
listView >> WM_SIZE >> hWnd:1443146,parent:262350
CreateListView >> rst:1,hwndlistview:853318,parent:1443146,hwndParent_:1443146, error:5
listview::init >> hWndMsgWindow:1443146,parent:262350, error:5
listview::init >> hWndListView:853318,parent:1443146,error:5
问题的关键是 WM_NOTIFY 消息的 return 值。
我输入了:
case WM_NOTIFY:
{
retnrn on_notify(hWnd,wParam,lParam);
}
问题已解决。
在微软网站上看到一篇文章MSDN介绍了一种高级的写法
我把它应用到class的扩展中,通常我没有问题。
但是最近在尝试写一个class的时候遇到了问题。 我想实现一个listview class 方便我们操作listview控件的时候
template <class DERIVED_TYPE>
class BaseWindow
{
public:
LPCTSTR className = "myWindows";
LPCTSTR Caption = "myWindows";
DWORD Style = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
UINT classStyle = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
DWORD ExStyle = 0;
...
other_property
...
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
DERIVED_TYPE *pThis = NULL;
if (uMsg == WM_NCCREATE)
{
CREATESTRUCT* pCreate = (CREATESTRUCT*)lParam;
pThis = (DERIVED_TYPE*)pCreate->lpCreateParams;
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis);
if (pThis)pThis->m_hwnd = hwnd;
}else{
pThis = (DERIVED_TYPE*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
if(pThis)pThis->m_hwnd = hwnd;
}
if (pThis)
{
return pThis->HandleMessage(hwnd, uMsg, wParam, lParam);
}else{
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
ATOM RegClass()
{
WNDCLASS wc = { 0 };
wc.lpfnWndProc = BaseWindow::WindowProc;
wc.hInstance = hInst;
wc.lpszClassName = className;
wc.style = classStyle;
wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
return RegisterClass(&wc);
}
BOOL CreateWinEx( LPCTSTR className_,LPCTSTR Caption_,
DWORD Style_,DWORD ExStyle_,
int x_,int y_,int w_,int h_,
HWND hWndParent_,HMENU hMenu_,HINSTANCE hInst_)
{
m_hwnd = CreateWindowEx(
ExStyle_, className_, Caption_, Style_,
x_, y_, w_, h_,
hWndParent_, hMenu_, hInst_, this
);
return (m_hwnd ? TRUE : FALSE);
}
BOOL Create()
{
ATOM rst = RegClass();
if(rst == 0) return FALSE;
m_hwnd = CreateWindowEx(
ExStyle, className, Caption, Style,
x, y, w, h,
hWndParent, hMenu, hInst, this
);
return (m_hwnd ? TRUE : FALSE);
}
}
基于以上,我导出了两个class,一个作为主窗体,一个作为我要设计的listviewclass
class FirstWindow : public BaseWindow<FirstWindow>
{
public:
FirstWindow(){};
...
some_property
...
LRESULT HandleMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK ButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
public:
};
class listView : public BaseWindow<listView>
{
public:
listView();
int init(LPCTSTR className_,HWND hWndParent_,int x,int y,int w,int h)
{
this->className = className_;
this->hWndParent = hWndParent_;
this->Style = WS_CHILD| WS_VISIBLE | ~WS_CAPTION;
this->x = x;
this->y = y;
this->w = w;
this->h = h;
this->Create();
hWndMsgWindow = m_hwnd;
CreateListView(hWndMsgWindow);
ShowWindow(hWndMsgWindow,SW_SHOW);
ShowWindow(hWndListView,SW_SHOW);
UpdateWindow(hWndMsgWindow);
UpdateWindow(hWndListView);
idebug("listview::init >> hWndMsgWindow:%d,parent:%d, error:%d\n",hWndMsgWindow,GetParent(hWndMsgWindow), GetLastError());
idebug("listview::init >> hWndListView:%d,parent:%d,error:%d\n",hWndListView,GetParent(hWndListView), GetLastError());
return 1;
}
LRESULT HandleMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT listView::CreateListView(HWND hwndParent_)
{
InitCommonControls();
bool rst = CreateWinEx(WC_LISTVIEW, NULL,
WS_CHILD | WS_VISIBLE | LVS_REPORT |LVS_EDITLABELS | LVS_NOCOLUMNHEADER | LVS_OWNERDATA |LVS_OWNERDRAWFIXED | WS_BORDER,0,
x,y,w,h,
hwndParent_, NULL, GetModuleHandle(NULL));
if(rst)
hWndListView = m_hwnd;
idebug("CreateListView >> rst:%d,hwndlistview:%d,parent:%d,hwndParent_:%d, error:%d\n",rst,hWndListView,GetParent(hWndListView),hwndParent_, GetLastError());
return rst;
}
LRESULT AddItem();
LRESULT OnListViewNotify(HWND hwnd, LPARAM lParam);
void OwnerDraw(LPDRAWITEMSTRUCT lpdis, HDC hdc, HWND hWnd, const TCHAR* szDraw);
void on_drawItem(HWND hWnd, LPARAM lParwm);
void on_notify(HWND hWnd, WPARAM wParwm, LPARAM lParam);
void on_create(HWND hWnd);
void on_measureItem(LPARAM lParam);
bool add_item();
bool add_item_sub();
...
some_property
...
};
首先触发 FirstWindow
FirstWindow * pFirstWnd;
listView lv;
int main(int argc, char** argv)
{
FirstWindow win;
pFirstWnd = &win;
win.className = "FirstWindow";
win.Style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
win.x = 100;
win.y = 100;
win.w = 600;
win.h = 300;
bool rst = win.Create();
if (!rst)
{
idebug("getlasterror:%d,line:201\n", GetLastError());
bug.ShowErr();
}
else {
lv.init("mylistview",pFirstWnd->m_hwnd,20,20,300,200);
ShowWindow(lv.m_hwnd, SW_SHOW);
}
MSG msg = {};
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
listview_class 的目标是能够独立接收和处理 window 消息。 不是这样的:
LRESULT FirstWindow::HandleMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE:
{
//lv.init("mylistview2",pFirstWnd->m_hwnd,20,20,300,200);
//ShowWindow(lv.m_hwnd, SW_SHOW);
break;
}
case WM_NOTIFY:
{
lv.on_notify(hWnd,wParam,lParam);
break;
}
...
}
default:
return DefWindowProc(m_hwnd, uMsg, wParam, lParam);
}
return TRUE;
}
相反,我想在列表视图中独立处理消息class,像这样:
LRESULT listView::HandleMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
static HDC hdc;
HRESULT lResult;
switch (uMsg)
{
case WM_CREATE:
{
idebug("class_listview >> WM_CREATE >> hWnd :%d, className:%s, parent:%d\n",hWnd, className , GetParent(hWnd));
//HWND h = CreateWindowEx(0, WC_LISTVIEW, NULL,
WS_CHILD | WS_VISIBLE | LVS_REPORT |LVS_EDITLABELS | LVS_NOCOLUMNHEADER | LVS_OWNERDATA |LVS_OWNERDRAWFIXED | WS_BORDER,
20,20,300,200,
hWnd,NULL, GetModuleHandle(NULL),NULL);
//ShowWindow(h,SW_SHOW);
//UpdateWindow(hWnd);
//idebug("class_listview >> WM_CREATE >> hwnd:%d,parent:%d,error:%d\n",h,GetParent(h), GetLastError());
//ShowWindow(h,SW_SHOW);
//UpdateWindow(h);
break;
}
case WM_NOTIFY:
{
on_notify(hWnd,wParam,lParam);
break;
}
case WM_MEASUREITEM:
{
on_measureItem(lParam);
break;
}
case WM_DRAWITEM:
{
on_drawItem(hWnd,lParam);
break;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 2));
EndPaint(hWnd, &ps);
idebug("class_listview >> WM_PAINT->hWnd:%d,id:%d,err:%d\n", hWnd, id, GetLastError());
break;
}
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
现在的问题是除了FirstWindow可以正常显示外,我看不到其他控件windows
更新: 来自调试的一些消息:
class_listview >> WM_CREATE >> hWnd :1443146, className:mylistview, parent:262350,error:0
listView >> WM_SIZE >> hWnd:1443146,parent:262350
CreateListView >> rst:1,hwndlistview:853318,parent:1443146,hwndParent_:1443146, error:5
listview::init >> hWndMsgWindow:1443146,parent:262350, error:5
listview::init >> hWndListView:853318,parent:1443146,error:5
问题的关键是 WM_NOTIFY 消息的 return 值。
我输入了:
case WM_NOTIFY:
{
retnrn on_notify(hWnd,wParam,lParam);
}
问题已解决。