Dialog window procedure as a member function of a class - c++

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...
}

Related

How to pass CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) input (mouse clicks, key press) to a class [duplicate]

I have been working with C++ and Win32 (non MFC/ATL) I am playing around with writing my own class library to wrap certain Win32 objects (HWNDs in particular).
When it comes to creating windows, I find the "RegisterClassEx / CreateWindowEx" method very awkward. This design makes it hard to write simple class wrappers (one must resort to thunks, or TLS or some other complicated mechanism).
It seems to me it would have been simpler to just let the application specify the window procedure and a user-data pointer at window creation time.
Is there any obvious reason I'm missing for the design choice here? Is there a really simple and efficient way for this to work?
ATL's CWindow and CWindowImpl are your friends.
CWindowImpl makes takes care of the RegisterClass/CreateWindow awkwardness that you speak of.
CWindow is a basic "wrapper" class for an HWND with all the win32 functions abstracted out.
The reason I prefer ATL over MFC. ATL is a very lightweight set of classes with all the source code provided. It's a simple #include with no extra libraries or runtimes to deal with. After rolling my own WndProcs and window encapsulation classes for many years, I've found CWindowImpl a joy to work with. You have to declare a global AtlModuleExe instance in your code to use it, but besides that, ATL stays out of the way.
Links to documenation for these classes below:
CWindow:
http://msdn.microsoft.com/en-us/library/d19y607d.aspx
CWindowImpl:
http://msdn.microsoft.com/en-us/library/h4616bh2.aspx
Update: Here's some sample code I dug up for you:
class CMyApp : public CAtlExeModuleT<CMyApp>
{
public:
static HRESULT InitializeCom()
{
CoInitialize(NULL);
return S_OK;
}
};
CMyApp g_app;
class CMyWindow : public CWindowImpl<CMyWindow>
{
public:
CMyWindow();
~CMyWindow();
BEGIN_MSG_MAP(CMyWindow)
MESSAGE_HANDLER(WM_PAINT, OnPaint);
MESSAGE_HANDLER(WM_CLOSE, OnClose);
END_MSG_MAP();
LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& fHandled);
LRESULT OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& fHandled);
};
LRESULT CMyWindow::OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& fHandled)
{
// your WM_PAINT code goes here
}
LRESULT CMyWindow::OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& fHandled)
{
PostQuitMessage();
}
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdline, int nCmdShow)
{
// 640x480 window
CMyWindow appwindow;
RECT rect = {0, 0, 640, 480};
RECT rectActual = {0};
appwindow.Create(NULL, rect, L"App Window", WS_OVERLAPPEDWINDOW);
appwindow.ShowWindow(SW_SHOW);
{
MSG msg;
while (GetMessage(&msg, 0, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
// app shutdown
appwindow.DestroyWindow();
return 0;
}
Resort to thunks or tls? I dont know what you mean by a thunk in this case, but its quite easy - if just a little convoluted - to bootstrap a window into a c++ class wrapper.
class UserWindow
{
HWND _hwnd;
public:
operator HWND(){
return _hwnd;
}
UserWindow():_hwnd(0){}
~UserWindow(){
if(_hwnd){
SetWindowLongPtr(GWL_USERDATA,0);
DestroyWindow(_hwnd);
}
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
UserWindow* self = 0;
if(uMsg == WM_CREATE)
{
LPCREATESTRUCT crst = (LPCREATESTRUCT)lParam;
self = (Window*)crst->lpCreateParams;
SetWindowLongPtr(hwnd,GWL_USERDATA,(LONG_PTR)self);
self->_hwnd = hwnd;
}
else
self = (Window*)GetWindowLongPtr(hwnd,GWL_USERDATA);
if(self){
LRESULT lr = self->WndProc(uMsg,wParam,lParam);
if(uMsg == WM_DESTROY){
if(self = (Window*)GetWindowLongPtr(hwnd,GWL_USERDATA))
self->_hwnd = NULL;
}
return lr;
}
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
HWND Create(int x, int y, int w, int h, LPCTSTR pszTitle,DWORD dwStyle,DWORD dwStyleEx,LPCTSTR pszMenu,HINSTANCE hInstance, HWND hwndParent){
WNDCLASSEX wcex = { sizeof (wcex),0};
if(!GetClassInfo(hInstance,ClassName(),&wcex)){
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WindowndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.lpszClassName = ClassName();
OnCreatingClass( wcex );
RegisterClassEx(&wcex);
}
return CreateWindowEx( dwStyleEx, ClassName(), pszTitle, dwStyle, x, y, w, h, hwndParent, pszMenu, hInstance, this);
}
// Functions to override
virtual LPCTSTR ClassName(){
return TEXT("USERWINDOW");
}
virtual LRESULT WindowProc(UINT uMsg, WPARAM wParam,LPARAM lParam){
return DefWindowProc(uMsg,wParam,lParam);
}
virtual void Window::OnCreatingClass(WNDCLASSEX& wcex){
wcex.hCursor = LoadCursor(NULL,IDC_ARROW);
}
};
It is all a bit convoluted, but it means that the window can be destroyed safely by deleting the class, OR by being destroyed. There are one or two sizing related messages sent during the call to CreateWindow before WM_CREATE sets GWL_USERDATA to "this" but practically they are of no consequence. The window class is automatically created the first time the window is instantiated.
One thing this style of automatic class registration on the first call to create does not support is the instantiation of this type of window as a control on a dialog - To support that case a whole slew of things would need to be changed... provide a static class registration function... a "new MyClass" in the static WM_CREATE handler... its not obvious to me how this could be done in a frameworkish type fashion.

How to prevent a system shutdown without having a window?

I have windows application with this source code
#include <Windows.h>
#include <thread>
#include <chrono>
int WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int cmdShow)
{
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WinProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch (Message)
{
case WM_QUERYENDSESSION:
MessageBox(NULL, "Triggered?", "Message", 0);
AbortSystemShutdown(NULL);
return 0;
default:
return DefWindowProc(hWnd, Message, wParam, lParam);
}
return 0;
}
I need to know when the system is shutting down and prevent it, or at least send a message to the user.
It doesn't seem that my application is receiving the WM_QUERYENDSESSION message.
I also tried to use ShutdownBlockReasonCreate() but I don't have a HWND for a window.
How should I do this?
As stated in the reference for WM_QUERYENDSESSION:
A window receives this message through its WindowProc function.
You have a WindowProc but you are missing a window. A WindowProc must be associated with a window, otherwise it is not known to Windows. To associate a WindowProc with a window, you can call RegisterClassEx followed by CreateWindowEx. Specify the name of your newly created window class in the call to CreateWindowEx.
The window must be a top-level window. It can be invisible, but in this case the following applies (from Application Shutdown Changes in Windows Vista):
Also note that if your application has no visible top-level windows,
it must use this API [ShutdownBlockReasonCreate()] if it needs to successfully block shutdown. Such
applications will automatically be terminated if they block shutdown
without using the API.
Note that a message-only window will not receive WM_QUERYENDSESSION.
Working example:
#include <windows.h>
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam );
int APIENTRY wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPWSTR lpCmdLine, int nCmdShow )
{
WNDCLASSEXW wx = { sizeof(wx) }; // set cbSize member and zero-initialize all other
wx.lpfnWndProc = WndProc;
wx.hInstance = hInstance;
wx.lpszClassName = L"MyWindowClass";
if( ! RegisterClassExW( &wx ) )
return 1; // TODO: improve error handling
HWND hWnd = CreateWindowExW( 0, wx.lpszClassName, L"My Application", 0, 0, 0, 0, 0,
NULL, NULL, NULL, NULL );
if( ! hWnd )
return 2; // TODO: improve error handling
MSG msg;
while( GetMessage( &msg, nullptr, 0, 0 ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
return static_cast<int>( msg.wParam );
}
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
switch( message )
{
case WM_QUERYENDSESSION:
{
// Try to block shutdown.
ShutdownBlockReasonCreate( hWnd, L"I don't want to sleep (yet)!" );
return FALSE;
}
case WM_ENDSESSION:
{
// TODO: Always handle this message because shutdown can be forced
// even if we return FALSE from WM_QUERYENDSESSION!
return 0;
}
default:
{
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
return 0;
}
Further read:
Application Shutdown Changes in Windows Vista
Restart Manager - Guidelines for Applications
Shutting Down

Windows Programming, window not opening, no build errors

I don't have much experience with windows programming, but can't specifically see what's wrong with this code, yet the window doesn't open. Although sometimes, not always, it will be open in task manager, so my guess is that it is registering the class and creating the window, but the problem is with the ShowWindow() function. But, I'm not positive.
To my understanding the flow of the program is:
Window is created with the registered class.
The window is shown.
Continuously looks for messages that are processed in the window Proc.
I feel like I've done all these things, so is my understanding wrong, or is my code missing something?
Thanks.
Source Code:
#include <Windows.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg == WM_DESTROY)
{
PostQuitMessage(0);
return 0;
}
DefWindowProc(hwnd, uMsg, wParam, lParam);
}
int WINAPI wWinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
//Variable for message loop.
MSG msg;
//Setting up the window class.
WNDCLASSEX windowClass;
windowClass.cbSize = sizeof(windowClass);
windowClass.style = CS_HREDRAW | CS_VREDRAW | CS_PARENTDC;
windowClass.lpfnWndProc = WindowProc;
windowClass.hInstance = hinstance;
windowClass.hbrBackground = (HBRUSH)COLOR_WINDOW;
windowClass.lpszClassName = "WindowClass";
RegisterClassEx(&windowClass);
HWND windowHandle = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, "WindowClass", "My Program", WS_OVERLAPPEDWINDOW, 500, 200, 800, 500, NULL, NULL, hinstance, 0);
if (!windowHandle)
return FALSE;
ShowWindow(windowHandle, nCmdShow);
// Start the message loop.
while (GetMessage(&msg, NULL, 0, 0) != 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Return the exit code to the system.
return msg.wParam;
}
Your window procedure is invoking DefWindowProc but not actually returning the result, and you have undefined behavior because of that. The return value is important, and it can control how the OS handles successive messages to your window. For example, it's important to return the correct value in response to the WM_CREATE message.
Change your window procedure to:
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg == WM_DESTROY)
{
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
Also, as Mark Ransom identified in the comments section, you should zero-initialize your WNDCLASSEX structure to ensure that you don't get garbage on any members that you didn't explicitly initialize.

I wrote some code in c to make simple win32 window but failed [duplicate]

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 8 years ago.
I'm getting this errors:
LNK1120: 1 unresolved externals on line 1
error LNK2019: unresolved external symbol _winproc#20 referenced in function _WinMain#16 C:\Users\giorgi\Documents\Visual Studio 2013\Projects\Hello\Hello\Source.obj Hello
I'm new to WinApi please help.
#include <windows.h>
LRESULT CALLBACK winproc(WNDPROC lpPrevWndFunc, HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR LpCmdLine, int nCmdShow)
{
WNDCLASSEX class;
ZeroMemory(&class, sizeof(WNDCLASSEX));
class.cbSize = sizeof(WNDCLASSEX);
class.style = CS_HREDRAW | CS_VREDRAW;
class.lpfnWndProc = (WNDPROC)winproc;
class.cbClsExtra = 0;
class.cbWndExtra = 0;
class.hInstance = hInstance;
class.hIcon = NULL;
class.hCursor = LoadCursor(NULL, IDC_ARROW);
class.hbrBackground = (HBRUSH)COLOR_WINDOW;
class.lpszClassName = "window class";
class.lpszMenuName = NULL;
class.hIconSm = NULL;
RegisterClassEx(&class);
HWND hwnd = CreateWindowEx
(
WS_EX_ACCEPTFILES,
"window class",
"window",
WS_OVERLAPPED,
200,
200,
800,
600,
NULL,
NULL,
hInstance,
NULL
);
ShowWindow(hwnd, nCmdShow);
MSG msg;
ZeroMemory(&msg, sizeof(MSG));
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
break;
}
return DefWindowProc(hwnd, msg, wp, lp);
}
As others have said, C is case-sensitive, so winproc and WinProc would be two different functions. You also need to insure that the signature of your windows procedure matches what Windows expect, so make the following changes:
change LRESULT CALLBACK winproc(WNDPROC lpPrevWndFunc, HWND hwnd, UINT msg, WPARAM wp, LPARAM lp); to LRESULT CALLBACK winProc(HWND, UINT, WPARAM, LPARAM);
change class.lpfnWndProc = (WNDPROC)winproc; to class.lpfnWndProc = (WNDPROC)winProc;
change LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) to LRESULT CALLBACK winProc(HWND hwnd, UINT mgs, WPARAM wp, LPARAM lp)
Finally, its been awhile since I programmed at the win32-API level, but I believe that you windows procedure should look like:
LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
break;
default:
return DefWindowProc(hwnd, msg, wp, lp);
}
}
In other words, you only want to return the default window proceedure (DefWindowProc) if you do not handle the message yourself.

Creating a window in OO

Here is my header
#pragma once
#ifndef BASE_H
#define BASE_H
#include <Windows.h>
#include <windowsx.h>
class Base
{
HWND hWnd;
WNDCLASSEX WndCls;
HRESULT Hr;
public:
Base();
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
void RegisterWnd(HINSTANCE hInstance);
void ShowWnd(int nCmdShow);
~Base();
};
#endif
Here is my base.cpp
#include "Base.h"
Base::Base()
{
}
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// sort through and find what code to run for the message given
switch (message)
{
// this message is read when the window is closed
case WM_DESTROY:
{
// close the application entirely
PostQuitMessage(0);
return 0;
} break;
}
// Handle any messages the switch statement didn't
return DefWindowProc(hWnd, message, wParam, lParam);
}
void Base::RegisterWnd(HINSTANCE hInstance)
{
ZeroMemory(&WndCls, sizeof(WNDCLASSEX));
WndCls.cbSize = sizeof(WNDCLASSEX);
WndCls.hbrBackground = (HBRUSH)COLOR_WINDOW;
WndCls.hCursor = LoadCursor(NULL, IDC_ARROW);
WndCls.hIcon = LoadIcon(hInstance, NULL);
WndCls.hIconSm = LoadIcon(hInstance, NULL);
WndCls.hInstance = hInstance;
WndCls.lpfnWndProc = WndProc;
WndCls.lpszClassName = "ClsName";
WndCls.style = CS_HREDRAW | CS_VREDRAW;
Hr = RegisterClassEx(&WndCls);
if (FAILED(Hr))
MessageBox(NULL, "Window Class failed to register.", "ERROR", MB_OK);
hWnd = CreateWindowEx(
NULL,
"WndClassName",
"WndName",
WS_OVERLAPPEDWINDOW,
100, 100,
480, 640,
NULL,
NULL,
hInstance,
NULL);
if (FAILED(hWnd))
MessageBox(NULL, "Window Class failed to create", "ERROR", MB_OK);
}
void Base::ShowWnd(int nCmdShow)
{
Hr = ShowWindow(hWnd, nCmdShow);
if (FAILED(Hr))
MessageBox(NULL, "Failed to display Window", "ERROR", MB_OK);
}
Base::~Base()
{
}
And here is my main.cpp
#include "Base.h"
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
Base CreateWnd;
CreateWnd.RegisterWnd(hInstance);
CreateWnd.ShowWnd(nCmdShow);
MSG Msg;
while (GetMessage(&Msg, NULL, 0, 0))
{
// translate keystroke messages into the right format
TranslateMessage(&Msg);
// send the message to the WindowProc function
DispatchMessage(&Msg);
}
// return this part of the WM_QUIT message to Windows
return Msg.wParam;
}
The problem is, I keep getting this error message that I dont understand of. Sorry for the bad explanation..Still a student in programming...
UPDATED :
The error above has been corrected by replacing
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
with
LRESULT CALLBACK Base::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
Thanks to ravi and IInspectable for the quick help.
Now I am having another error D: When i clicked on debug, everything run perfectly but nothing shows up. No window is showing. Visual studio is running perfectly as "Ready". (Sorry i do not want to make another new question because it's still related to creating window in oo
SECOND UPDATE :
My class name in CreateWindowEx is different from the RegisterWnd..My bad. Thanks to IInspectable again for the help.
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
You have to define this with class scope OR how compiler know if its global static OR static member of class. So it should be
LRESULT CALLBACK Base::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)