2013-08-23 171 views
1

我做了我的研究,但無法找到答案。我發現的最接近的是「Cannot create window」,但它沒有幫助我。所以,在這裏!Win32窗口無法創建?

基本信息

我有一個靜態庫和使用靜態庫的應用程序。我將應用程序正確連接到靜態庫(包括目錄,庫目錄,實際庫依賴關係等)。在靜態庫中,我有1個文件:IWindow.h。在應用程序中,我有3個文件:Main.cpp,WindowMain.hWindowMain.cppIWindow.h定義了一個抽象窗口類:

#ifndef IWINDOW_H 
#define IWINDOW_H 

#include <Windows.h> 

namespace NamespaceName 
{ 
    template<class T> 
    class IWindow 
    { 
    public: 
     static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); 

     virtual ~IWindow(){} 

     virtual LRESULT handleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) = 0; 
     virtual VOID paint(HDC hDC) = 0; 

     VOID create(HINSTANCE hI, LPCWSTR title, LPCWSTR className, DWORD dwStyle, DWORD dwExStyle = 0, int x = CW_USEDEFAULT, int y = CW_USEDEFAULT, int nWidth = CW_USEDEFAULT, int nHeight = CW_USEDEFAULT, HWND hWndParent = 0, HMENU hMenu = 0); 

     HWND getHWND(); 
     BOOL isCreated(); 
    protected: 
     HWND m_hWnd; 
     BOOL created; 
    }; 

    template<class T> 
    LRESULT CALLBACK IWindow<T>::windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 
    { 
     T* pThis = NULL; 

     if(uMsg == WM_NCCREATE) 
     { 
      CREATESTRUCT* pCreate = (CREATESTRUCT*)lParam; 
      pThis = (T*)pCreate->lpCreateParams; 
      SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)pThis); 
     } 
     else 
     { 
      pThis = (T*)GetWindowLongPtr(hWnd, GWLP_USERDATA); 
     } 

     if(pThis) 
     { 
      return pThis->handleMessage(uMsg, wParam, lParam); 
     } 
     else 
     { 
      return DefWindowProc(hWnd, uMsg, wParam, lParam); 
     } 
    } 

    template<class T> 
    VOID IWindow<T>::create(HINSTANCE hI, LPCWSTR title, LPCWSTR className, DWORD dwStyle, DWORD dwExStyle = 0, int x = CW_USEDEFAULT, int y = CW_USEDEFAULT, int nWidth = CW_USEDEFAULT, int nHeight = CW_USEDEFAULT, HWND hWndParent = 0, HMENU hMenu = 0) 
    { 
     WNDCLASS windowClass = {0}; 
     windowClass.hInstance = hI; 
     windowClass.lpszClassName = className; 
     windowClass.style = CS_HREDRAW | CS_VREDRAW; 
     windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); 
     windowClass.hCursor = LoadCursor(NULL, IDC_ARROW); 
     windowClass.lpfnWndProc = IWindow::windowProc; 

     RegisterClass(&windowClass); 

     m_hWnd = CreateWindowEx(dwExStyle, className, title, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, GetModuleHandle(NULL), this); 

     created = (m_hWnd ? TRUE : FALSE); 
    } 

    template<class T> 
    HWND IWindow<T>::getHWND() 
    { 
     return m_hWnd; 
    } 

    template<class T> 
    BOOL IWindow<T>::isCreated() 
    { 
     return created; 
    } 
} 

#endif 

然後,

WindowMain.h定義IWindow.h

代碼的一個子類:

#ifndef WINDOWMAIN_H 
#define WINDOWMAIN_H 

#include <FolderName\Video\GUI\IWindow.h> 

class WindowMain : public NamespaceName::IWindow<WindowMain> 
{ 
public: 
    ~WindowMain(){} 

    LRESULT handleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); 
    VOID paint(HDC hDC); 
}; 

#endif 

而且,

它伴隨.cpp文件

完成它:

#include "WindowMain.h" 

LRESULT WindowMain::handleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) 
{ 
    HDC hDC; 
    PAINTSTRUCT ps; 

    switch(uMsg) 
    { 
    case WM_DESTROY: 
     PostQuitMessage(0); 
     return 0; 
    case WM_PAINT: 
     { 
      hDC = BeginPaint(m_hWnd, &ps); 

      FillRect(hDC, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1)); 
      paint(hDC); 

      EndPaint(m_hWnd, &ps); 
     } 
     return 0; 
    } 

    return DefWindowProc(m_hWnd, uMsg, wParam, lParam); 
} 

VOID WindowMain::paint(HDC hDC) 
{ 
} 

最後,

Main.cpp

代碼:

#include <Windows.h> 
#include <tchar.h> 
#include <GdiPlus.h> 
#include "WindowMain.h" 

#pragma comment(lib, "Gdiplus.lib") 

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) 
{ 
    WindowMain window; 
    MSG msg; 
    Gdiplus::GdiplusStartupInput gdiplusStartupInput; 
    ULONG_PTR gdiplusToken; 

    Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); 

    window.create(hInstance, L"Test Window", L"Test Window Class", WS_OVERLAPPEDWINDOW); 

    if(!window.isCreated()) 
     return 1; 

    ShowWindow(window.getHWND(), nCmdShow); 
    UpdateWindow(window.getHWND()); 

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

    Gdiplus::GdiplusShutdown(gdiplusToken); 

    return 0; 
} 

window.isCreated()總是返回false,從而使if聲明中Main.cpp將其反轉爲true並始終返回1並退出應用程序。如果我省略Main.cpp中的if語句,那麼該窗口不會顯示出來,並且應用程序會一直運行,直到我在IDE中強制停止它。

其他問題(如果您想評論的答案,這些都是可選的,並且不涉及到前一個問題以任何方式)

我不喜歡的Visual Studio的。我更喜歡使用NetBeans。我試圖用它來進行Windows編程,但我失敗了。我是否必須使用Visual Studio進行Windows編程?它是否有一些可以用特殊方式編譯Win32程序的神奇編譯器?或者我只是做錯了什麼?

這些Gdiplus令牌和啓動輸入是什麼?一個解釋它的地方的鏈接將會很棒。

最後

感謝您抽出時間來閱讀這一點,並有可能試圖幫助我。如果您需要更多信息,我會很樂意提供。如果問題構建得不好,請讓我知道如何改進它,我會。;)

編輯#1

發現這一點: 「Win32 API window won't open」,只爲記錄​​,它並沒有幫助我的情況下,無論是。

編輯#2

IWindow.h,當我創建一個WNDCLASS,爲窗口過程中,我試圖用T::windowProc,而不是IWindow::windowProc,但它並沒有幫助。

編輯#3

找到 「WinAPI window doesn't appear」,但沒有幫助。

編輯#4

「嘗試設置windowClass.cbWndExtra註冊前級爲sizeof(LONG_PTR)」。 - 從評論中推斷。試過了,也沒有幫助。

編輯#5

試圖與RegisterClassEx更換WNDCLASSWNDCLASSEXRegisterClass並添加windowClassEx.cbSize = sizeof(WNDCLASSEX)(我從windowClass改變了變量名windowClassEx太),但並沒有幫助...

+4

我實際上並不經常使用VS編程,所以沒有。 – chris

+0

好的,感謝您提供的信息,我會爲它做一些更多的研究。我很高興我不必使用它:P –

+0

嘗試在註冊類之前將windowClass.cbWndExtra設置爲sizeof(LONG_PTR)。 – user1233963

回答

5

我看到至少有兩個錯誤。

首先,你註冊類

windowClass.hInstance = hI; 

但是當你創建窗口,傳遞不同的HINSTANCE

m_hWnd = CreateWindowEx(dwExStyle, className, title, dwStyle, x, y, 
      nWidth, nHeight, hWndParent, hMenu, GetModuleHandle(NULL), this); 
//           ^^^^^^^^^^^^^^^^^^^^^ 

HINSTANCE參數必須按順序爲類是匹配找到。你應該在兩個地方使用hI

其次,您的代碼在初始化之前使用m_hWnd成員。

return DefWindowProc(m_hWnd, uMsg, wParam, lParam); 

當窗口接收WM_NCCREATE消息,m_hWnd尚未初始化。在CreateWindowEx返回之前它不會被初始化。你需要得到正確的窗口句柄DefWindowProc。一種方法是將hWnd參數從windowproc傳遞到handlemessage。另一種是添加

m_hWnd = hWnd; 

在您的if(uMsg == WM_NCCREATE)

請注意,您的代碼假定如果GWLP_USERDATA非零,那麼m_hWnd是有效的。但是,你沒有做任何事情來使這個假設有效。在收到WM_NCCREATE消息和完成CreateWindowEx之間,您有一個非零GWLP_USREDATA,但m_hWnd未初始化。

調試的方法是在窗口過程中設置一個斷點並逐步完成。在逐步處理WM_NCCREATE消息時,您應該已經注意到m_hWnd未初始化。

此代碼中存在第三個錯誤,一旦您創建窗口,您最終會發現其中一個錯誤:當窗口被銷燬時,您從未將m_hWnd設置回NULL

+0

非常感謝!這確實有助於解決問題,我不知道我是如何錯過這些事情的!今後應該多加關注我猜:P –