Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed last month.
Improve this question
I am new to the Win32 API, and I tried making my own calculator, but when I run the code, the edit control starts to glitch, and I can't see what has been inputted.
I tried adding a button which stores the value 1 into the edit control (where the text of the calculator will be displayed), but whenever I use the button, or try to type directly, the text starts to glitch.
#include <windows.h>
#include <stdlib.h>
#define ONE_BUTTON 1
/*#define TWO_BUTTON 2
#define THREE_BUTTON 3
#define FOUR_BUTTON 4
#define FIVE_BUTTON 5
#define SIX_BUTTON 6
#define SEVEN_BUTTON 7
#define EIGHT_BUTTON 8
#define NINE_BUTTON 9
#define TEN_BUTTON 0*/
void AddControls(HWND);
HWND hOut;
HWND hOne;
LRESULT CALLBACK WindowProcedure(HWND,UINT,WPARAM,LPARAM);
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst , LPSTR args, int ncmdshow)
{
WNDCLASSW wc = {0};
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hInstance = hInst;
wc.lpszClassName = L"mywindowclass";
wc.lpfnWndProc = WindowProcedure;
if(!RegisterClassW(&wc))
return -1;
CreateWindowW(L"mywindowclass",L"calculatorGUi",WS_OVERLAPPEDWINDOW|WS_VISIBLE,100,100,500,350,NULL,NULL,NULL,NULL);
MSG msg = {0};
while(GetMessage(&msg,NULL,NULL,NULL))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
LRESULT CALLBACK WindowProcedure(HWND hWnd,UINT msg,WPARAM wp,LPARAM lp)
{
switch(msg)
{
case WM_COMMAND:
switch (wp)
{
case ONE_BUTTON:
char one[50];
char out[15];
GetWindowText(hOne,one,50);
strcpy(out,one);
SetWindowText(hOut,out);
}
case WM_CREATE:
AddControls(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
default:
return DefWindowProcW(hWnd,msg,wp,lp);
}
}
void AddControls(HWND hWnd)
{
hOut = CreateWindowW(L"Edit",(int)NULL,WS_VISIBLE|WS_CHILD|WS_BORDER,2,2,480,106,hWnd,NULL,NULL,NULL);
hOne= CreateWindowW(L"Button",L"1",WS_VISIBLE|WS_CHILD|BS_RADIOBUTTON|BS_DEFPUSHBUTTON 2,110,98,50,hWnd,(HMENU)ONE_BUTTON,NULL,NULL);
/*CreateWindowW(L"Button",L"2",WS_VISIBLE|WS_CHILD,102,110,99,50,hWnd,(HMENU)TWO_BUTTON,NULL,NULL);
CreateWindowW(L"Button",L"3",WS_VISIBLE|WS_CHILD,202,110,99,50,hWnd,(HMENU)THREE_BUTTON,NULL,NULL);
CreateWindowW(L"Button",L"4",WS_VISIBLE|WS_CHILD,302,110,99,50,hWnd,(HMENU)FOUR_BUTTON,NULL,NULL);
CreateWindowW(L"Button",L"5",WS_VISIBLE|WS_CHILD,402,110,80,50,hWnd,(HMENU)FIVE_BUTTON,NULL,NULL);
CreateWindowW(L"Button",L"6",WS_VISIBLE|WS_CHILD,2,165,99,50,hWnd,(HMENU)SIX_BUTTON,NULL,NULL);
CreateWindowW(L"Button",L"7",WS_VISIBLE|WS_CHILD,102,165,99,50,hWnd,(HMENU)SEVEN_BUTTON,NULL,NULL);
CreateWindowW(L"Button",L"8",WS_VISIBLE|WS_CHILD,202,165,99,50,hWnd,(HMENU)EIGHT_BUTTON,NULL,NULL);
CreateWindowW(L"Button",L"+",WS_VISIBLE|WS_CHILD,302,165,99,50,hWnd,(HMENU)NINE_BUTTON,NULL,NULL);
CreateWindowW(L"Button",L"-",WS_VISIBLE|WS_CHILD,402,165,99,50,hWnd,(HMENU)TEN_BUTTON,NULL,NULL);
CreateWindowW(L"Button",L"9",WS_VISIBLE|WS_CHILD,2,220,99,50,hWnd,NULL,NULL,NULL);
CreateWindowW(L"Button",L"0",WS_VISIBLE|WS_CHILD,102,220,99,50,hWnd,NULL,NULL,NULL);
CreateWindowW(L"Button",L"*",WS_VISIBLE|WS_CHILD,202,220,99,50,hWnd,NULL,NULL,NULL);
CreateWindowW(L"Button",L"/",WS_VISIBLE|WS_CHILD,302,220,99,50,hWnd,NULL,NULL,NULL);
CreateWindowW(L"Button",L"=",WS_VISIBLE|WS_CHILD,402,220,99,50,hWnd,NULL,NULL,NULL);*/
}
Your WM_COMMAND and ONE_BUTTON cases are both missing break statements, so whenever the Edit sends update notifications to your main window, or whenever the button is clicked, your code falls through to call AddControls(), creating more and more child controls on top of the previous child controls, and reusing the same child IDs.
Also, your ONE_BUTTON handler has a buffer overflow if the user enters text with more than 14 characters.
Try this instead:
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch(msg)
{
case WM_COMMAND:
switch (wp)
{
case ONE_BUTTON: {
char one[50] = {};
GetWindowText(hOne, one, 50);
SetWindowText(hOut, one);
break; // <-- add this!
}
break; // <-- add this!
case WM_CREATE:
AddControls(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break; // <-- add this!
default:
return DefWindowProcW(hwnd, msg, wp, lp);
}
return 0; // <-- add this!
}
Based on this post, I'm trying to create a simple Win32 application, in which the window procedure/callback function of a dialog window is a member function of a class. My code looks like this:
H file:
class MyClass
{
public:
HINSTANCE hInstance;
HWND hWnd;
int APIENTRY WinMainProc(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
static LRESULT CALLBACK WinProcWraper(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
LRESULT CALLBACK WinProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
ATOM MyClassRegisterClass(HINSTANCE hInstance);
};
CPP file:
LRESULT CALLBACK MyClass::WinProcWraper(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
if (WM_NCCREATE == message)
{
SetWindowLong (hWnd, GWL_USERDATA, (long)((CREATESTRUCT*) lParam)->lpCreateParams);
return TRUE;
}
return ((MyClass*) GetWindowLong (hWnd, GWL_USERDATA))->WinProc (hWnd, message, wParam, lParam);
}
int APIENTRY MyClass::WinMainProc(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
MyClass.hInstance=hInstance;
MyClass.MyClassRegisterClass(hInstance);
//MY PROBLEM IS HERE: cannot convert parameter 4 to int
HWND hWnd = CreateDialog(hInstance,MAKEINTRESOURCE(IDD_MAIN_DIALOG), 0, (DLGPROC)MyClass::WinProc);
ShowWindow(hWnd,nCmdShow);
UpdateWindow(hWnd);
while (GetMessage(&msg, NULL, 0, 0))
{
if (!IsWindow(hWnd) || !IsDialogMessage(hWnd,&msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return static_cast<int>(msg.wParam);
}
LRESULT CALLBACK MyClass::WinProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
(...)
}
When calling CreateDialog(), I get the following error:
cannot convert from 'long (__stdcall MyClass::*)(struct HWND__ *,unsigned int,unsigned int,long)'
to 'long (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long)'
How can I make the correct type conversion in this case?
Lets start with the error message. You are trying to use a non-static class method, WinProc(), as your CreateDialog() callback. That will not work. You went to the trouble of implementing a static class method, WinProcWraper(), which calls WinProc(), but you are not actually using it. You need to use WinProcWraper() as the actual window procedure for CreateDialog().
Also, there is no need to type-cast WinProcWraper when passing it to CreateDialog(), if its signature is correct to begin with (which yours is not).
After fixing that, you still have other problems:
the other code you are modeling after was designed for a window procedure for CreateWindow/Ex(), but you are using CreateDialog() instead, which has different requirements.
Since you are using CreateDialog() instead of CreateWindow/Ex(), WinProcWraper() and WinProc() need to return a BOOL instead of an LRESULT. If an actual LRESULT value needs to be returned to the system, WinProc() will need to use SetWindowLong(DWL_MSGRESULT) for that purpose.
WinProcWraper() is expecting to receive a WM_NCCREATE message to deliver it a MyClass* pointer, which it will then assign to the HWND. But, since you are using CreateDialog(), WinProcWraper() will not receive any WM_(NC)CREATE messages, it will receive a WM_INITDIALOG message instead. And even then, CreateDialog() does not allow you to pass any user-defined value to the window procedure, so you can't pass in the MyClass* pointer that WinProcWraper() requires. You need to use CreateDialogParam() instead for that.
WM_INITDIALOG may not be the first message a window receives, just the first message that can give you access to the MyClass* pointer that you pass to CreateDialogParam(). WinProcWraper() needs to handle the possibility that it can receive messages before it has received access to the MyClass* pointer.
You are using SetWindowLong(). Your code will not work if it is ever compiled for 64bit. Use SetWindowLongPtr() instead, even for 32bit code.
With that said, try this:
class MyClass
{
public:
HINSTANCE hInstance;
HWND hWnd;
int APIENTRY WinMainProc(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
BOOL CALLBACK WinProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
ATOM MyClassRegisterClass(HINSTANCE hInstance);
private:
static BOOL CALLBACK WinProcWraper(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
};
BOOL CALLBACK MyClass::WinProcWraper(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
MyClass *cls;
if (WM_INITDIALOG == uMsg)
{
cls = reinterpret_cast<MyClass*>(lParam);
SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(cls));
}
else
cls = reinterpret_cast<MyClass*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
if (cls)
return cls->WinProc(uMsg, wParam, lParam);
return FALSE;
}
int APIENTRY MyClass::WinMainProc(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
MyClass.hInstance = hInstance;
MyClass.MyClassRegisterClass(hInstance);
HWND hWnd = CreateDialogParam(hInstance, MAKEINTRESOURCE(IDD_MAIN_DIALOG), NULL, MyClass::WinProcWraper, reinterpret_cast<LPARAM>(this));
if (!hWnd)
return -1;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while (GetMessage(&msg, NULL, 0, 0))
{
if (!IsWindow(hWnd) || !IsDialogMessage(hWnd, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return static_cast<int>(msg.wParam);
}
BOOL CALLBACK MyClass::WinProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
...
if (needed)
SetWindowLongPtr(hWnd, DWLP_MSGRESULT, ...);
return ...; // TRUE or FALSE as needed...
}
I am creating a program of painting a text in multiline edit using windows api in c++. It consists of WM_PAINT message which paints the text in client area, but the caret shows unexpected behaviour in edit. It sometimes does not print characters, sometimes printed characters hides.
The code is
#define UNICODE
/*
**
**ALL HEADER FILES
**
*/
#include<wchar.h>
#include<windows.h>
#include <errno.h>
#include<conio.h>
#include<iostream>
#include<stdio.h>
#include<resource.h>
/*
**
**ALL DEFINES CONSTANT
**
*/
#define WINVER 0x0A00
#define _WIN32_WINNT 0x0A00
LRESULT CALLBACK WindowProcedure(HWND,UINT,WPARAM,LPARAM);
using namespace std;
HWND hwnd_handle;
HWND hw;
HINSTANCE his;
int WINAPI WinMain(HINSTANCE hvalue,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
his=hvalue;
/////com=nCmdShow;
LPWSTR myname=L"MY WINDOWS CLASS";
MSG msg={0};
WNDCLASSW wc;
wc.hbrBackground=(HBRUSH)COLOR_BTNFACE;
wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wc.lpszMenuName=NULL;
wc.lpszClassName=myname;
wc.hCursor=NULL;
wc.cbClsExtra=0;
wc.cbWndExtra=0;
wc.style=0;
wc.hInstance=hvalue;
wc.lpfnWndProc=WindowProcedure;
if(!RegisterClassW(&wc))
{
return 0;
}
///////main window
hwnd_handle=CreateWindowW(myname,L"CODE EDITOR",WS_OVERLAPPEDWINDOW,240,80,600,600,NULL, NULL,hvalue, NULL);
ShowWindow(hwnd_handle,nCmdShow);
UpdateWindow(hwnd_handle);
////////HWND hwnd=CreateWindowW(L"STATIC",L"CODE EDITOR",WS_OVERLAPPEDWINDOW,24,8,60,6,hwnd_handle, NULL,hInstance, NULL);
while(GetMessageW(&msg,NULL,NULL,NULL))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT msg,WPARAM wParam,LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
{
/////main_structure(hwnd);
hw=CreateWindowW(TEXT("edit"),TEXT(""), WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_HSCROLL|ES_MULTILINE|ES_AUTOHSCROLL|ES_AUTOVSCROLL ,3,0,600,600,hwnd,NULL,his,NULL);
}
break;
case WM_COMMAND:
{
/////menu_function(hwnd,wParam);
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
RECT info;
HBRUSH hbrush;
HDC hdc = BeginPaint(hw,&ps);
wcout<<"vishal";
TextOut(hdc,20,20,L"vishak",6);
EndPaint(hw,&ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
break;
}
}
///////all men
Since you are using an edit control as the client area of your window don't handle WM_PAINT yourself; instead add the text to the edit control (using SendMessage with EM_SETTEXT or possibly EM_REPLACESEL) and let it do the drawing.
Also, you should handle WM_SIZE and set the edit control to the actual client area size.
I'm working on window in the winapi that displays a cef browser. My code compiles without errors and doesn't run into any runtime errors, but while my window displays, my cef webpage does not (my window is entirely blank). I've spent about 6 hours going about this but still haven't got anything to work.
I have my window in a separate class from my main function, and I think that might be the cause of my problems, as my g_handler might not be passed correctly.
Thanks for your help!
I stripped all of my windows api code of my examples (as it has been working fine) to keep my code samples short.
Here is my code:
Winmain:
#include "trackboxWrapper.h"
#include <stdexcept>
#include <thread>
#include "include\cef_app.h"
CefRefPtr<trackboxCefHandler> g_handler;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
try
{
CefMainArgs main_args(hInstance);
int exitCode = CefExecuteProcess(main_args, NULL);
if (exitCode >= 0) {
return exitCode;
}
CefSettings settings;
CefRefPtr<CefApp> cefApplication;
CefInitialize(main_args, settings, cefApplication);
trackboxWrapper window(g_handler);
CefRunMessageLoop();
CefShutdown();
}
catch (std::exception& e)
{
MessageBoxA(0, (std::string("Trackox Internal Error \n\n") + e.what()).c_str(), "=(", 0);
}
}
trackboxWrapper(only cef relavent parts are shown):
header(trackboxWrapper.h):
[code]#include <windows.h>
#include "include\cef_app.h"
#include "include\cef_base.h"
#include "include\cef_browser.h"
#include "include\cef_client.h"
class trackboxWrapper
{
public:
CefRefPtr<trackboxCefHandler> & g_handler;
trackboxWrapper(CefRefPtr<trackboxCefHandler> g_handler_pointer);
~trackboxWrapper();
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
}
cpp(trakcboxWrapper.cpp):
trackboxWrapper::trackboxWrapper(CefRefPtr<trackboxCefHandler> g_handler_pointer) : g_handler(g_handler_pointer) {}
LRESULT CALLBACK trackboxWrapper::WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
trackboxWrapper *window = reinterpret_cast<trackboxWrapper*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
if (!window) return DefWindowProc(hwnd, msg, wparam, lparam);
switch (msg)
{
case WM_CREATE:
{
window->g_handler = new trackboxCefHandler();
RECT trackboxCefRect;
GetClientRect(hwnd, &trackboxCefRect);
CefWindowInfo info;
CefBrowserSettings settings;
info.SetAsChild(hwnd, trackboxCefRect);
CefBrowserHost::CreateBrowser(info, window->g_handler.get(), L"http://www.google.com", settings);
}
}
trackboxCefHandler.h:
#ifndef TRACKBOXCEFHANDLER_H_
#define TRACKBOXCEFHANDLER_H_
#include "include/cef_client.h"
class trackboxCefHandler : public CefClient {
public:
trackboxCefHandler() {}
~trackboxCefHandler() {}
IMPLEMENT_REFCOUNTING(trackboxCefHandler);
IMPLEMENT_LOCKING(trackboxCefHandler);
};
#endif
You create g_handler in three places, that might be your problem.
One is in the file with your Winmain (first code snippet where you declare this variable).
CefRefPtr<trackboxCefHandler> g_handler;
Another is in trackboxWrapper.h.
class trackboxWrapper
{
public:
CefRefPtr<trackboxCefHandler> g_handler;
....
And the third one is in trackboxWrapper.cpp:
case WM_CREATE:
{
CefRefPtr<trackboxCefHandler> g_handler = new trackboxCefHandler();
These are three different variables because they are fully declared in each of these places, so they shadow each other too (though the one in header file gets initialized with the argument in constructor, which leaves two).
You definitely don't need to create it in the third snippet, because you have already declared g_handler in your header:
case WM_CREATE:
{
window->g_handler = new trackboxCefHandler();
will be enough.
That way you should have the same object everywhere.
I did my research but couldn't find an answer. The closest thing I found is "Cannot create window", but it didn't help me. So, here it is!
Basic info
I have a static library and an application using a static library. I hooked up the application to the static library correctly (Include directories, library directories, actual library dependencies, etc). In the static library i have 1 file: IWindow.h. In the application I have 3 files: Main.cpp, WindowMain.h and WindowMain.cpp. IWindow.h defines an abstract window class:
#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
Then,
WindowMain.h defines a subclass of IWindow.h
Code:
#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
And,
it's accompanying .cpp file
completes it:
#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)
{
}
And finally,
the Main.cpp
Code:
#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;
}
The window.isCreated() always returns false, thus making the if statement in the Main.cpp invert it to true and always returning 1 and exiting the application. If I omit the if statement from Main.cpp the window does not show up and the application goes on forever, until i force-stop it in the IDE.
Additional questions (answer in comments if you want, these are optional and do not relate to the former question in any way)
I don't like Visual Studio at all. I prefer using NetBeans so much more. I tried to use it for Windows programming but I failed. Do I have to use Visual Studio for Windows programming? Does it have some magical compiler that can compile Win32 programs in a special way? Or am I just doing something wrong?
What are these Gdiplus tokens and startup input? A link to somewhere that explains it would be awesome.
Finally
Thank you for taking your time to read this, and potentially trying to help me. If you need any more information I'll be happy to provide it. If the question was poorly constructed please let me know how to improve it and I will. ;)
Edit #1
Found this: "Win32 API window won't open", just for the record, it didn't help my case either.
Edit #2
In IWindow.h, when I was creating a WNDCLASS, for the window process, I tried to use T::windowProc instead of IWindow::windowProc, but it didn't help either.
Edit #3
Found "WinAPI window doesn't appear", but didn't help either.
Edit #4
"Try setting windowClass.cbWndExtra to sizeof(LONG_PTR) before registering the class." -suggestion from the comments. Tried it too, and also didn't help.
Edit #5
Tried replacing WNDCLASS with WNDCLASSEX and RegisterClass with RegisterClassEx and added windowClassEx.cbSize = sizeof(WNDCLASSEX) (I changed the variable name from windowClass to windowClassEx too), but didn't help either...
I see at least two errors.
First, you register the class with
windowClass.hInstance = hI;
but when you create the window, you pass a different HINSTANCE:
m_hWnd = CreateWindowEx(dwExStyle, className, title, dwStyle, x, y,
nWidth, nHeight, hWndParent, hMenu, GetModuleHandle(NULL), this);
// ^^^^^^^^^^^^^^^^^^^^^
The HINSTANCE parameters must match in order for the class to be found. You should use hI in both places.
Second, your code uses the m_hWnd member before it is initialized.
return DefWindowProc(m_hWnd, uMsg, wParam, lParam);
When the window receives the WM_NCCREATE message, m_hWnd has not yet been initialized. It doesn't get initialized until the CreateWindowEx returns. You need to get the correct window handle to DefWindowProc. One way is to pass the hWnd parameter from windowproc through to handlemessage. Another is to add
m_hWnd = hWnd;
in your if(uMsg == WM_NCCREATE).
Notice that your code assumes that if GWLP_USERDATA is nonzero, then m_hWnd is valid. However, you did nothing to actually make this assumption valid. Between the receipt of the WM_NCCREATE message and the completion of CreateWindowEx, you have a nonzero GWLP_USREDATA but m_hWnd is not initialized.
The way to debug this is to set a breakpoint on your window procedure and step through it. When stepping through the handling of the WM_NCCREATE message, you should have noticed that m_hWnd is not initialized.
There is a third bug in this code, which you would eventually stumble across once you get the window created: You never set m_hWnd back to NULL when the window is destroyed.