新人自学Windows程序设计,照着网上找的视频教程把一些API函数封装了一下,结果显示的跟说好的不一样。本来应该创建一个Button按钮,结果却没有显示,求指导。
本人初学顾没什么重点,所以废话比较多,并且只好将能贴出来的代码都贴出来,为了节省版面一些头文件和声明什么的都没贴出来,程序中几乎所有的接口函数都是虚函数。
关于消息循环的概念基本没有,只是依葫芦画瓢,教程怎么说我就怎么写,个人关于这个程序的理解是这样的:
1.入口函数里的InitInstance由于虚函数多态性调用到QDemoWinApp中的InitInstance;
2.在QDemoWinApp中的InitInstance中用QMainFrame产生一个对象并通过这个对象调用该对象基类QWnd中的CreateEx来注册和创建窗口;
3.完了之后在CreateEx中自己发送一个WM_CREATE,由于自己封装了一个新的回调函数,顾调用到派生类QMainFrame中的OnCreate从而调用到QButton中CreateEx创建一个BUTTON(结果却没创建)
程序如下:
int WINAPI _tWinMain(IN HINSTANCE hInstance,IN HINSTANCE hPreInstance,IN LPTSTR lpCmdLine,IN int nShowCmd) { QWinApp* pWinApp = GlbGetApp(); assert(pWinApp); pWinApp->InitInstance(); pWinApp->Run(); pWinApp->ExitInstance(); return TRUE; }
QWinApp
QWinApp::QWinApp(void) { m_pMainWnd = NULL; g_pWinApp = this; } QWinApp::~QWinApp(void) { } BOOL QWinApp::InitInstance() { return TRUE; } BOOL QWinApp::ExitInstance() { return TRUE; } void QWinApp::Run() { MSG msg; while(::GetMessage(&msg,NULL,NULL,NULL)) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } }
QDemoWinApp
QDemoWinApp::QDemoWinApp(void) { } QDemoWinApp::~QDemoWinApp(void) { } QDemoWinApp theApp; BOOL QDemoWinApp::InitInstance() { QMainFrame* pMainWnd = new QMainFrame(); assert(pMainWnd); m_pMainWnd = pMainWnd; BOOL bRet = pMainWnd ->CreateEx(0,_T("拓拓拓"),_T("拓拓拓"),WS_VISIBLE|WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL); if(!bRet) { ::MessageBox(NULL,_T("创建窗口失败"),_T("创建窗口"),0); return FALSE; } pMainWnd ->ShowWindow(SW_SHOW); pMainWnd ->UpdateWindow(); return TRUE; } BOOL QDemoWinApp::ExitInstance() { if(m_pMainWnd) { delete m_pMainWnd; m_pMainWnd = NULL; } return TRUE; }
QWnd
1 LRESULT CALLBACK QWnd::WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) 2 { 3 if(uMsg == WM_CREATE || uMsg == WM_NCCREATE) 4 { 5 LPCREATESTRUCT pCs = (LPCREATESTRUCT)lParam; 6 if(pCs) 7 { 8 QWnd* pWnd = (QWnd*)pCs->lpCreateParams; 9 if(pWnd) 10 { 11 pWnd->m_hWnd = hWnd; 12 pWnd->m_lpfnOldWndProc = (WNDPROC)(LONG_PTR)GetWindowLong(hWnd,GWL_WNDPROC); 13 return pWnd->Windowproc(uMsg,wParam,lParam); 14 } 15 } 16 } 17 18 QWnd* pWnd = (QWnd*)(LONG_PTR)GetWindowLong(hWnd,GWL_USERDATA); 19 if(pWnd) 20 { 21 return pWnd->Windowproc(uMsg,wParam,lParam); 22 } 23 24 return ::DefWindowProc(hWnd,uMsg,wParam,lParam); 25 //return ::DefWindowProc(hWnd,uMsg,wParam,lParam); 26 } 27 28 LRESULT QWnd::Windowproc(UINT uMsg,WPARAM wParam,LPARAM lParam) 29 { 30 switch(uMsg) 31 { 32 case WM_CLOSE: 33 { 34 return OnClose(wParam,lParam); 35 } 36 break; 37 case WM_DESTROY: 38 { 39 return OnDestroy(wParam,lParam); 40 } 41 break; 42 case WM_CREATE: 43 { 44 return OnCreate(wParam,lParam); 45 } 46 break; 47 default: 48 break; 49 } 50 return Default(uMsg,wParam,lParam); 51 } 52 53 LRESULT QWnd::Default(UINT uMsg,WPARAM wParam,LPARAM lParam) 54 { 55 if(m_lpfnOldWndProc==QWnd::WndProc) 56 { 57 return ::DefWindowProc(m_hWnd,uMsg,wParam,lParam); 58 } 59 60 return m_lpfnOldWndProc(m_hWnd,uMsg,wParam,lParam); 61 } 62 63 //msg 64 LRESULT QWnd::OnClose(WPARAM wParam,LPARAM lParam) 65 { 66 return Default(WM_CLOSE,wParam,lParam); 67 } 68 69 LRESULT QWnd::OnDestroy(WPARAM wParam,LPARAM lParam) 70 { 71 return Default(WM_DESTROY,wParam,lParam); 72 } 73 74 LRESULT QWnd::OnCreate(WPARAM wParam,LPARAM lParam) 75 { 76 return Default(WM_CREATE,wParam,lParam); 77 } 78 79 QWnd::QWnd(void) 80 { 81 m_hWnd = NULL; 82 m_lpfnOldWndProc = NULL; 83 } 84 85 QWnd::~QWnd(void) 86 { 87 } 88 89 BOOL QWnd::PreCreateWindow(CREATESTRUCT& cs) 90 { 91 92 WNDCLASSEX wcex; 93 wcex.cbSize = sizeof(WNDCLASSEX); 94 BOOL bRet = ::GetClassInfoEx(cs.hInstance,cs.lpszClass,&wcex); 95 if(bRet) 96 { 97 return TRUE; 98 } 99 /*注册窗口*/ 100 101 wcex.style =CS_HREDRAW | CS_VREDRAW; 102 wcex.lpfnWndProc = WndProc; 103 wcex.cbClsExtra = 0; 104 wcex.cbWndExtra = 0; 105 wcex.hInstance = cs.hInstance; 106 wcex.hIcon = (HICON)::LoadIcon(NULL,IDI_APPLICATION); 107 wcex.hIconSm = (HICON)::LoadIcon(NULL,IDI_APPLICATION); 108 wcex.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH); 109 wcex.hCursor = (HCURSOR)::LoadCursor(NULL,IDC_ARROW); 110 wcex.lpszMenuName = NULL; 111 wcex.lpszClassName = cs.lpszClass; 112 bRet = ::RegisterClassEx(&wcex); 113 if(!bRet) 114 { 115 ::MessageBox(NULL,_T("窗口注册失败"),_T("注册窗口"),0); 116 return FALSE; 117 118 } 119 return TRUE; 120 121 } 122 123 124 BOOL QWnd::CreateEx( 125 DWORD dwExStyle, 126 LPCTSTR lpszClassName, 127 LPCTSTR lpszWindowName, 128 DWORD dwStyle, 129 int x, 130 int y, 131 int nWidth, 132 int nHeight, 133 HWND hWndParent, 134 HMENU nIDorHMenu, 135 LPVOID lpParam 136 ) 137 { 138 HINSTANCE hInstance = (HINSTANCE)::GetModuleHandle(NULL); 139 assert(hInstance); 140 CREATESTRUCT cs; 141 cs.cx = nWidth; 142 cs.cx = nHeight; 143 cs.dwExStyle = dwExStyle; 144 cs.hInstance = hInstance; 145 cs.hMenu = nIDorHMenu; 146 cs.hwndParent = hWndParent; 147 cs.lpCreateParams = lpParam; 148 cs.lpszClass = lpszClassName; 149 cs.lpszName = lpszWindowName; 150 cs.style = dwStyle; 151 cs.x = x; 152 cs.y = y; 153 154 BOOL bRet = PreCreateWindow(cs); 155 if(!bRet) 156 { 157 ::MessageBox(NULL,_T("注册窗口类失败"),_T("注册窗口"),0); 158 return FALSE; 159 } 160 161 HWND hWnd = ::CreateWindowEx(cs.dwExStyle,cs.lpszClass,cs.lpszName,cs.style,cs.x,cs.y, 162 cs.cx,cs.cy,cs.hwndParent,cs.hMenu,cs.hInstance,this); 163 if(NULL == hWnd) 164 { 165 return FALSE; 166 } 167 m_hWnd = hWnd; 168 SetWindowLong(m_hWnd,GWL_USERDATA,(LONG)(LONG_PTR)this); 169 170 m_lpfnOldWndProc = (WNDPROC)(LONG_PTR)GetWindowLong(m_hWnd,GWL_WNDPROC); 171 if(m_lpfnOldWndProc != QWnd::WndProc) 172 { 173 // 子类化 174 SetWindowLong(m_hWnd,GWL_WNDPROC,(long)QWnd::WndProc); 175 Windowproc(WM_CREATE,0,0); 176 Windowproc(WM_NCCREATE,0,0); 177 } 178 return TRUE; 179 } 180 181 BOOL QWnd::ShowWindow(int nCmdShow) 182 { 183 assert(m_hWnd); 184 return ::ShowWindow(m_hWnd,nCmdShow); 185 } 186 BOOL QWnd::UpdateWindow() 187 { 188 189 assert(m_hWnd); 190 return ::UpdateWindow(m_hWnd); 191 192 } 193 BOOL QWnd::DestroyWindow() 194 { 195 assert(m_hWnd); 196 return ::DestroyWindow(m_hWnd); 197 198 }
QMainFrame
QMainFrame::QMainFrame(void) { } QMainFrame::~QMainFrame(void) { } //msg LRESULT QMainFrame::OnClose(WPARAM wParam,LPARAM lParam) { return DestroyWindow(); } LRESULT QMainFrame::OnDestroy(WPARAM wParam,LPARAM lParam) { PostQuitMessage(0); return TRUE; } LRESULT QMainFrame::OnCreate(WPARAM wParam,LPARAM lParam) { if(NULL==m_wndButton.m_hWnd) { m_wndButton.CreateEx(_T("拓"),WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,0,0,200,120,m_hWnd,(HMENU)IDC_BUTTON); } return TRUE; }
QButton
QButton::QButton(void) { } QButton::~QButton(void) { } BOOL QButton::CreateEx( LPCTSTR lpszWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU nIDorHMenu ) { return QWnd::CreateEx(0,_T("BUTTON"),lpszWindowName,dwStyle,x,y,nWidth,nHeight,hWndParent,nIDorHMenu); }
首先,针对楼主的代码,在回调函数中(Windowproc)添加一个WM_PAINT消息,这是进行一些绘制工作的消息,在此消息下进行按钮的创建,并获取父窗口的句柄,将该按钮添加到该句柄上就可以啦,对于楼主说的消息循环机制,楼主可以这样理解,一个Win32程序如果想在屏幕上持续显示是需要进行死循环才可以的,对应楼主的代码就是Run函数啦,建议楼主还是了解一些Win32程序的运行机制,我只能帮你到这啦!
QT?
没学过QT,QT不是应该把接口都封装好了吗
@tangshaotuo: 这个我就不晓得了。