Я сделал свое исследование, но не смог найти ответ. Самое близкое, что я нашел, это «Cannot create window», но это меня не помогло. Итак, вот оно!Окно Win32 не удается создать?
Базовая информация
У меня есть статические библиотеки и приложения, используя статическую библиотеку. Я правильно подключил приложение к статической библиотеке (включите каталоги, библиотечные каталоги, фактические зависимости библиотек и т. Д.). В статической библиотеке у меня есть 1 файл: IWindow.h
. В приложении у меня есть 3 файла: Main.cpp
, WindowMain.h
и WindowMain.cpp
. IWindow.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 и выходит из приложения. Если я опускаю оператор if
от Main.cpp
, окно не отображается, и приложение продолжается вечно, пока я не закрою его в среде IDE.
Дополнительные вопросы (ответ в комментариях, если вы хотите, они не являются обязательными и не касаются первого вопроса в любом случае)
Мне не нравится Visual Studio на всех. Я предпочитаю использовать NetBeans намного больше. Я попытался использовать его для программирования Windows, но я потерпел неудачу. Должен ли я использовать программу Visual Studio для Windows? Есть ли у него какой-то магический компилятор, который может скомпилировать программы Win32 особым образом? Или я просто делаю что-то неправильно?
Что представляют собой эти жетоны Gdiplus и ввод в эксплуатацию? Ссылка на то, что объясняет это, было бы потрясающе.
Наконец
Спасибо за ваше время, чтобы прочитать это, и, возможно, пытается помочь мне. Если вам нужна дополнительная информация, я буду рад предоставить ее. Если вопрос был плохо сконструирован, пожалуйста, дайте мне знать, как его улучшить, и я это сделаю.;)
Редактировать # 1
Нашел: "Win32 API window won't open", только для записи, это не помогло мое дело тоже.
Edit # 2
В IWindow.h
, когда я создавал WNDCLASS
, для процесса окна, я пытался использовать T::windowProc
вместо IWindow::windowProc
, но это не помогло.
Edit # 3
Найдено "WinAPI window doesn't appear", но не помогло.
Редактировать # 4
"Попробуйте установить windowClass.cbWndExtra на SizeOf (LONG_PTR) перед регистрацией класса." - из комментариев. Пробовал тоже, а также не помог.
Редактировать # 5
Пробовал заменить WNDCLASS
с WNDCLASSEX
и RegisterClass
с RegisterClassEx
и добавил windowClassEx.cbSize = sizeof(WNDCLASSEX)
(я изменил имя переменной из windowClass
в windowClassEx
тоже), но не помогло ...
Я не использую VS для программирования Windows слишком часто, поэтому нет. – chris
Хорошо, спасибо за информацию, тогда я сделаю еще несколько исследований. Я так рад, что мне не нужно его использовать: P –
Перед регистрацией класса попробуйте установить windowClass.cbWndExtra на sizeof (LONG_PTR). – user1233963