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.
Related
Maybe this is just a code organization issue, maybe there is some extremely fundamental C++ knowledge that I am lacking -- I have tried for hours to arrive at a reasonable solution, and nothing appears to work, so I am turning to the internet.
I am writing a Direct2D application for game development, and I am trying to get mouse coordinates from the WndProc lParam when there is a WM_MOUSEMOVE message, as is outlined and recommended in the MSDN article here. Here is how the relevant portions of the project are configured.
window.h
struct Window {
HWND _hwnd;
bool Initialize(int width, int height);
void RunMessageLoop();
};
window.cpp
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_MOUSEMOVE:
int xPosAbsolute = GET_X_PARAM(lParam); // as is suggested by MSDN
int yPosAbsolute = GET_Y_PARAM(lParam); // as is suggested by MSDN
...
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
bool Window::Initialize(int width, int height) {
WNDCLASS wc;
wc.lpfnWndProc = WndProc;
// etc...
}
void Window::RunMessageLoop() {
MSG Msg;
while (true)
{
GetMessage(&Msg, NULL, 0, 0);
TranslateMessage(&Msg);
DispatchMessage(&Msg);
};
}
main.cpp
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow)
{
// ...
while (true) {
int absolute_mouse_pos_x = ???;
int absolute_mouse_pos_y = ???;
// etc...
}
return 0;
}
My question: How can I reasonably assign (and update) absolute_mouse_pos_x and absolute_mouse_pos_y in main.cpp with the xPosAbsolute/yPosAbsolute values from the WndProc function in window.cpp?
The first thing that came to mind was instancing the WndProc function so that it has access to the members of the Window struct, but this is impossible/impractical due to the signature of a member function having a hidden "this" parameter, as other answers on Stack Overflow such as this one have detailed.
After that, I tried creating global variables in window.h, assigning them in the WndProc function in window.cpp, and referencing them in main.cpp. main.cpp could use the initial values of both global variables, but updating those global variables with new values later seemed to be completely invisible to main.cpp (I am wondering if these globals were implicitly read-only, but this may just be lack of understanding/user error on my part). Aside from this behavior, common wisdom is that globals shouldn't be used unless absolutely necessary, and it seems weird to have to use globals for something so seemingly simple. Is there no simpler/better way?
Thanks!
Here are some possible ways to accomplish this.
GetCursorPos()
This is very simple, and returns the screen coordinates of the cursor, not the coordinates within a window. This could be (un)desirable based on the application you're making. You can use ScreenToClient() to convert these coordinates to window coordinates.
Here is an example using main.cpp for simplicity, but could be done in any other translation unit.
main.cpp
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow)
{
// ...
POINT p;
while (true) {
GetCursorPos(&p);
int absolute_mouse_pos_x = p.x;
int absolute_mouse_pos_y = p.y;
// etc...
}
return 0;
}
Get/SetWindowLongPtr
This is more complex, but gives you window coordinates of the cursor (through the lParam of the WM_MOUSEMOVE message), and allows you to get/set state of a custom structure of your choice inside of WndProc. Here are the changes to window.h & window.cpp that are needed to implement this, and an example of accessing these variables from a separate translation unit (main.cpp).
window.h
struct Window {
HWND _hwnd;
int mouse_x;
int mouse_y;
bool Initialize(int width, int height);
// etc..
};
window.cpp
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
Window* window;
if (msg == WM_CREATE)
{
CREATESTRUCT* pCreate = reinterpret_cast<CREATESTRUCT*>(lParam);
window = reinterpret_cast<Window*>(pCreate->lpCreateParams);
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)window);
}
else
{
LONG_PTR ptr = GetWindowLongPtr(hwnd, GWLP_USERDATA);
window = reinterpret_cast<Window*>(ptr);
}
switch (msg)
{
case WM_MOUSEMOVE:
window->mouse_x = GET_X_PARAM(lParam);
window->mouse_y = GET_Y_PARAM(lParam);
break;
// etc...
}
return 0;
}
bool Window::Initialize(int width, int height) {
WNDCLASS wc;
wc.lpfnWndProc = WndProc;
// etc...
CreateWindowEx(.., this); // add the "this" pointer as the last argument to CreateWindowEx()
}
main.cpp
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow)
{
// ...
Window w;
w.Initialize(width, height);
while (true) {
int absolute_mouse_pos_x = w.mouse_x;
int absolute_mouse_pos_y = w.mouse_y;
// etc...
}
return 0;
}
I'm trying to recreate the famous Windows 93 Hydra virus for Windows 95 using Microsoft Visual C++ 4.0, but due to my inexperience with Win32 I'm having trouble launching the main dialog box.
Here is what I was able to come with so far (the rest of the code can be found in this github repo):
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "resource.h"
static HINSTANCE hInstanceGlobal;
BOOL CALLBACK DialogProc(HWND H, UINT M, WPARAM W, LPARAM L);
inline int CreateHead()
{
return DialogBox(hInstanceGlobal,
MAKEINTRESOURCE(HYDRA),
0, DialogProc);
}
BOOL CALLBACK DialogProc(HWND H, UINT M, WPARAM W, LPARAM L)
{
switch (M)
{
case WM_COMMAND:
CreateHead();
CreateHead();
case WM_INITDIALOG:
return TRUE;
default:
return FALSE;
}
}
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
hInstanceGlobal = hInstance;
return CreateHead();
}
The program compiles, but when I run it does absolutely nothing.
What am I doing wrong? How could I achieve the desired effect?
I want to use GDI+ with Pascal scripting which doesn't provide GDI+ natively, but I don't know why When using dll(shared), the process will not exit even when the window is destroyed, I mean to say I can still see the process running from the task manager though it doesn't have any window to see. The process remains at idle i.e without any resource usage
In my dll, for every new hwnd i am hooking my own wndproc and on WM_Paint message i am drawing the specified objects that are so far are requested to be drawn
I am exporting DrawRectangle symbol for drawing and compiling for 32-bit
my dll is
#include <Windows.h>
#include <gdiplus.h>
using namespace Gdiplus;
#include <objidl.h>
#pragma comment(lib, "Gdiplus.lib")
#include <functional>
#include <map>
#include <memory>
#include <vector>
#define DLL_EXPORT(RETURN_TYPE) \
extern "C" __declspec(dllexport) RETURN_TYPE __stdcall
void msg(const char *str) { MessageBoxA(nullptr, str, "Message", 0); }
void msg(const wchar_t *str) { MessageBoxW(nullptr, str, L"Message", 0); }
class _GdiManager {
public:
_GdiManager() {
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr);
}
~_GdiManager() { GdiplusShutdown(gdiplusToken); }
private:
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
} GdiManager;
class DrawableObject {
public:
virtual void draw(Gdiplus::Graphics &Graphics) = 0;
virtual ~DrawableObject() = default;
};
namespace DrawableObjects {
class Rectangle : public DrawableObject {
public:
Rectangle(ARGB Color, int X, int Y, int Width, int Height)
: m_X{X}, m_Y{Y}, m_Width{Width}, m_Height{Height}, m_Brush{Color} {}
void draw(Gdiplus::Graphics &graphics) override {
graphics.FillRectangle(&m_Brush, m_X, m_Y, m_Width, m_Height);
}
private:
int m_X, m_Y, m_Width, m_Height;
Gdiplus::SolidBrush m_Brush;
};
} // namespace DrawableObjects
LRESULT MasterWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
class Painter {
public:
Painter(HWND hWnd) : m_WindowHandle{hWnd}, m_Graphics{hWnd} {
m_OriginalWindowProc = (WNDPROC)GetWindowLongW(m_WindowHandle, GWL_WNDPROC);
SetWindowLongW(m_WindowHandle, GWL_WNDPROC, (LONG)MasterWindowProc);
}
LRESULT CallOriginalWndProc(HWND hwnd, UINT uMsg, WPARAM wParam,
LPARAM lParam) {
return CallWindowProcW(m_OriginalWindowProc, hwnd, uMsg, wParam, lParam);
}
LRESULT Paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
if (uMsg == WM_PAINT) {
for (auto &o : m_Objects)
o->draw(m_Graphics);
} else if (uMsg == WM_DESTROY) {
PostQuitMessage(0);
}
return 0;
}
std::vector<std::unique_ptr<DrawableObject>> &Objects() { return m_Objects; }
private:
HWND m_WindowHandle;
Gdiplus::Graphics m_Graphics;
WNDPROC m_OriginalWindowProc;
std::vector<std::unique_ptr<DrawableObject>> m_Objects;
};
std::map<HWND, std::unique_ptr<Painter>> windowPaint;
LRESULT MasterWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
auto &p = windowPaint[hwnd];
auto r = p->CallOriginalWndProc(hwnd, uMsg, wParam, lParam);
p->Paint(hwnd, uMsg, wParam, lParam);
return r;
}
auto &insertPainter(HWND hwnd) {
auto &my_painter = windowPaint[hwnd];
if (!my_painter)
my_painter = std::make_unique<Painter>(hwnd);
return my_painter;
}
DLL_EXPORT(int)
DrawRectangle(HWND hwnd, ARGB LineColor, int startX, int startY, int width,
int height) {
auto &my_painter = insertPainter(hwnd);
my_painter->Objects().push_back(std::make_unique<DrawableObjects::Rectangle>(
LineColor, startX, startY, width, height));
return 0;
}
the host program:
//#include "gdi.cpp"
#include <ObjIdl.h>
#include <Windows.h>
#include <cassert>
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment(lib, "Gdiplus.lib")
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR, INT iCmdShow) {
HWND hWnd;
MSG msg;
WNDCLASS wndClass;
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WndProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = hInstance;
wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = TEXT("GettingStarted");
RegisterClass(&wndClass);
hWnd = CreateWindow(TEXT("GettingStarted"), // window class name
TEXT("Getting Started"), // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL); // creation parameters
ShowWindow(hWnd, iCmdShow);
UpdateWindow(hWnd);
auto dll = LoadLibraryW(L"isGDI.dll");
assert(dll);
auto DrawRectangle = (int(__stdcall *)(
HWND, DWORD, int, int, int, int))GetProcAddress(dll, "DrawRectangle");
assert(DrawRectangle);
DrawRectangle(hWnd, 0xffff0000, 0, 0, 100, 100);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
FreeLibrary(dll);
return msg.wParam;
} // WinMain
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
LPARAM lParam) {
return DefWindowProc(hWnd, message, wParam, lParam);
} // WndProc
also, the program will work as expected if I call DrawRectangle directly through the source code (without using DLL)
i view that you use global object GdiManager inside dll. this meant that it destructor called from DLL_PROCESS_DETACH, so inside LoaderLock critical section. in destructor you call GdiplusShutdown. when GdiplusShutdown called inside LoaderLock and GDI+ use background thread ( suppressBackgroundThread = FALSE - this is your case) this is always cause deadlock:
GdiplusShutdown signal to background thread exit (set Globals::ThreadQuitEvent) and then wait for background thread exit. thread when exiting try enter to LoaderLock and hung here - because it hold by thread which call GdiplusShutdown. so main thread hung in wait for backgound thread and bacground thread hung in enter LoaderLock critical section.
we can try use suppressBackgroundThread = TRUE, but in this case need call NotificationUnhook. if do this on DLL_PROCESS_DETACH already UB (based on implementation) this can look like ok, or hung, or fail (inside this called for example DestroyWindow which is also error from dll entry, also error if process detach will be called on different thread (compare dll attach) - so window will be created inside NotificationHook on another thread)
correct solution here will be export 2 additional functions from dll , say Start and Stop, and from first call GdiplusStartup and from second GdiplusShutdown. call Start just after dll load and Stop before unload
You are not telling the current thread (the app) to exit. Use PostQuitMessage in the WndProc associated with the window:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
LPARAM lParam) {
if (message == WM_DESTROY)
PostQuitMessage(0);
else
return DefWindowProc(hWnd, message, wParam, lParam);
return 0;
}
I want to know if there is a way i could write this code shorter, if there is anyway to make a #define that can shorten the way im doing my if statements in the message switch.
I check if i have set up a function if there is i then call it
This is just apart of my wndproc it is alot bigger
LRESULT Base::WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch (uMsg)
{
case WM_CREATE:
{
if (this->onCreate != NULL)
{
if (onCreate(hwnd, (LPCREATESTRUCT)lParam))
return 1;
}
}break;
case WM_DESTROY:
{
if (onDestroy != NULL)
{
if (onDestroy(hwnd))
return 1;
}
this->Destroy();
}break;
case WM_SIZE:
{
if (onSize != NULL)
{
if (onSize(hwnd, wParam, lParam))
return 1;
}
}break;
case WM_CLOSE:
{
if (onClose != NULL)
{
if (onClose(hwnd))
return 1;
}
}break;
default:
{
}break;
}
return ::DefWindowProc(hwnd, uMsg, wParam, lParam);
}
pointers defined like this
LRESULT(*onCreate) (HWND, LPCREATESTRUCT);
I then add them like this
LRESULT onCreate(HWND, LPCREATESTRUCT)
{
return true;
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR pCmdLine, int nCmdShow)
{
Window mainWindow;
mainWindow.onCreate = onCreate;
return 0;
}
Use the message-cracker macros defined in <WindowsX.h>. This won't actually make the code run any faster, and it doesn't really result in a net loss of lines of code, but it certainly makes the code easier to read, which is the important part. Nobody wants to look at a 1000-line switch statement. Plus, these macros extract the parameters for each message from WPARAM and LPARAM, enhancing readability, reducing mistakes and simplifying what you have to remember.
The macros are pretty simple and anything but high-tech (they originated way back in the 16-bit Windows days):
#define HANDLE_MSG(hwnd, message, fn) \
case (message): return HANDLE_##message((hwnd), (wParam), (lParam), (fn))
But they are pre-defined for all of the most common messages (you can add your own for the two or three messages that they omitted if you find that you need them), so you don't have to deal with the ugliness. You just get nice, readable code:
#include <Windows.h>
#include <WindowsX.h> // for the message cracker macros
...
void Base::OnClose(HWND hWnd)
{
// ...
}
BOOL Base::OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct)
{
// ...
return TRUE;
}
void Base::OnDestroy(HWND hWnd)
{
// ...
}
void Base::OnSize(HWND hWnd, UINT state, int cx, int cy)
{
// ...
}
LRESULT Base::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
HANDLE_MSG(hWnd, WM_CLOSE, OnClose);
HANDLE_MSG(hWnd, WM_CREATE, OnCreate);
HANDLE_MSG(hWnd, WM_DESTROY, OnDestroy);
HANDLE_MSG(hWnd, WM_SIZE, OnSize);
// TODO: Add more message crackers here to handle additional messages.
default:
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
The header file also contains comments showing the signature of the handler function. But check out HernĂ¡n Di Pietro's Message Cracker Wizard to make your life even easier. It lists all of the messages, allows you to filter them down to the ones you're looking for, and will automatically copy the template code to the clipboard!
To avoid the definition of all possible specific (virtual) message-handlers in the base class, you may have a map of handlers:
#include <unordered_map>
// Mokup windows.h
typedef intptr_t HWND;
typedef intptr_t LRESULT;
typedef intptr_t WPARAM;
typedef intptr_t LPARAM;
typedef unsigned UINT;
enum {
WM_CREATE
};
// Base
class WindowBase
{
public:
virtual ~WindowBase() {}
LRESULT WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
// The complexity of finding an element in an unordered map
// is amortized O(1).
auto kv = window_procedures.find(uMsg);
if(kv != window_procedures.end()) {
auto procedure = kv->second;
return (this->*procedure)(hwnd, uMsg, wParam, lParam);
}
return 0; //::DefWindowProc(hwnd, uMsg, wParam, lParam);
}
protected:
typedef LRESULT (WindowBase::*window_procedure)(HWND, UINT msg, WPARAM, LPARAM);
template <typename Procedure>
void register_window_procedure(UINT msg, Procedure procedure) {
window_procedures[msg] = static_cast<window_procedure>(procedure);
}
private:
std::unordered_map<UINT, window_procedure> window_procedures;
};
// Test
#include <iostream>
class Window : public WindowBase
{
public:
Window() {
register_window_procedure(WM_CREATE, &Window::onCreate);
}
protected:
LRESULT onCreate(HWND, UINT msg, WPARAM, LPARAM) {
std::cout << "onCreate\n";
return 0;
}
};
int main() {
Window w;
WindowBase* p = &w;
p->WindowProc(0, WM_CREATE, 0, 0);
}
Note: This is not following your example using a freestanding message handler. If you want that, you may typedef LRESULT (*window_procedure)(HWND, UINT msg, WPARAM, LPARAM); and adjust the code accordingly. However, the function signature should include an extra argument (e.g.: WindowBase*) to keep the context (besides HWND), in which the message is invoked.
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 8 years ago.
Improve this question
I cant seem to figure out what is problem here. The error is highlighted under hInstance
#include "Game.h"
#include "WindowApp.h"
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT Msg,WPARAM wParam, LPARAM lParam);
//---------------------------------------------------------------------------
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst,LPSTR lpCmdLine, int nCmdShow)
{
MSG Msg;
LPCTSTR ClsName = "Win32OOP";
LPCTSTR WndName = "Object-Oriented Win32 Programming";
// Initialize the application class
Game WinApp(hInstance, ClsName, MainWndProc); // Error here. Screenshot below
WinApp.RegWndClass();
// Create the main window
WindowApp Wnd;
Wnd.Create(hInstance, ClsName, WndName);
Wnd.Show();
// Process the main window's messages
while (GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return 0;
}
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT Msg,WPARAM wParam, LPARAM lParam)
{
switch (Msg)
{
case WM_DESTROY:
PostQuitMessage(WM_QUIT);
return 0;
}
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
Here is the Game.h
#ifndef GAME_H
#define GAME_H
#define Win32_LEAN_AND_MEAN
// Include the basic windows header file
#include <Windows.h>
#include <windowsx.h>
class Game
{
// Global variable that holds the application
WNDCLASSEX _WndClsEx;
public:
Game();
// This constructor will initialize the application
Game(HINSTANCE hInst, char *ClasName,WNDPROC WndPrc, LPCTSTR MenuName = NULL);
// Class Registration
void RegWndClass();
~Game();
};
#endif
Here is the link that i refer to : http://www.functionx.com/win32/Lesson06.htm
Your problem is that you pass HINSTANCE, LPCTSTR, WNDPROC to Game constructor. But it expects HINSTANCE, char *, WNDPROC. TLPCTSTR is not the same as char*.
Simply change the signature of Game constructor to Game(HINSTANCE, LPCTSTR, WNDPROC).