external variable is not available to thread until blocking call is made... - c++

I have two code files, one contains my WinMain() function, and all functions related to my main dialog window. The other contains a thread callback and variable functions related to my program. I have defined HWND hWnd = NULL as a global variable in MainDlg.cpp and defined extern HWND hWnd in Other.cpp (which contains the thread callback). The thread is created when the WM_INITDIALOG message is sent to the window. Inside the thread callback, the hWnd variable is null until long operation is performed, then after that it becomes available.
MainDlg.cpp
HWND hWnd = NULL;
HANDLE hListenThread = NULL;
DWORD WINAPI ListenThread( LPVOID lpvParam );
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
/* ... */
if( NULL == (hWnd=CreateDialog( hInstance, MAKEINTRESOURCE(IDD_MAINDLG), NULL, (DLGPROC)WndProc)) )
{
MessageBox( NULL, "Error creating the main dialog!", NULL, MB_OK | MB_ICONERROR );
return -1;
}
MSG msg;
while( GetMessage(&msg,NULL,0,0) && IsWindow(hWnd) )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
BOOL CALLBACK WndProc(HWND hWndDlg, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch(Message)
{
case WM_INITDIALOG:
{
DWORD dwListenThreadId = NULL;
/* referencing hWnd here works fine... */
/* ... */
hListenThread = CreateThread(
NULL,
0,
ListenThread,
hWndDlg,
0,
&dwListenThreadId);
/* ... */
} break;
}
return false;
}
Other.cpp
extern HWND hWnd;
DWORD WINAPI ListenThread( LPVOID lpvParam )
{
if( hWnd == NULL )
MessageBox( NULL, "hWnd == NULL", NULL, MB_OK | MB_SYSTEMMODAL );
if( hWnd != NULL )
MessageBox( NULL, "hWnd != NULL", NULL, MB_OK | MB_SYSTEMMODAL );
return 0;
}
Both Message Boxes in the ListenThread callback are displayed when the application is launched. Can someone please tell me why this is happening? Is there something I can do to fix this besides doing while( hWnd == NULL ); at the beginning of my ListenThread ?

The WM_INITDIALOG message occurs before CreateDialog returns and hWnd isn't set until CreateDialog returns. So the thread starts running before CreateDialog returns and sets the global hWnd variable.
So you could fix this by moving your thread creation from the WM_INITDIALOG message to just after the return of CreateDialog.
But you don't need to do that because you code doesn't required the global hWnd variable. You are already passing your dialogs window handle as the parameter to the thread start procedure. So just cast the lpvParam to an HWND and use that. That will let you get rid of your global variable, which is bad practice to use.
Other.cpp
DWORD WINAPI ListenThread( LPVOID lpvParam )
{
HWND hWnd= (HWND)lpvParam;
if( hWnd == NULL )
MessageBox( NULL, "hWnd == NULL", NULL, MB_OK | MB_SYSTEMMODAL );
if( hWnd != NULL )
MessageBox( NULL, "hWnd != NULL", NULL, MB_OK | MB_SYSTEMMODAL );
return 0;
}

The WM_INITDIALOG message is issued to WndProc() from inside of CreateDialog() itself, not by DispatchMessage(). This is stated as much in the CreateDialog() documentation. Your hWnd variable is not assigned until after CreateDialog() exits. If your thread starts running before CreateDialog() exits (depending on task scheduling, that is not a guarantee), your first MessageBox() gets called. While the MessageBox() is running, CreateDialog() has time to exit and assign the variable, which is why the second MessageBox() gets called after you dismiss the first MessageBox().
You don't need to use the hWnd variable in your thread at all. You are passing the dialog HWND to the lpParameter parameter of CreateThread(), so it will appear in the lpvParam parameter of ListenThread(), eg:
DWORD WINAPI ListenThread( LPVOID lpvParam )
{
HWND hWnd = (HWND) lpvParam;
...
return 0;
}

Related

Make a event for a mouse button even if application is minimized

I want to make an application that responds to a mouse button so I done this:
case WM_LBUTTONDOWN:
MessageBox(
NULL,
(LPCWSTR)L"HALLOOOO",
(LPCWSTR)L"Worked",
MB_ICONASTERISK | MB_OK | MB_DEFBUTTON2
);
break;
but the problem is that this only works if the user clicks on the window and I want it to work even with the window minimized
this work even if the application is minimized
GetKeyState(VK_LBUTTON);
but if I put this in a loop if I press it once it will detect 1 million times because it will just check if the key is down and if I add delay using Sleep(250) it may work but sometimes it will not detect anything even if the user pressed the key
I want my app to be able to detect if a key is pressed even if it's minimized how can I do this?
Since you already have a window, call SetWindowsHookEx with WH_MOUSE_LL.
The API is documented here and the parameters are explained.
HHOOK SetWindowsHookExW(
[in] int idHook,
[in] HOOKPROC lpfn,
[in] HINSTANCE hmod,
[in] DWORD dwThreadId
);
The lpfn hook procedure can be defined as follows:
HWND hmain_window;
HHOOK hhook;
LRESULT CALLBACK mouse_proc(int code, WPARAM wparam, LPARAM lparam)
{
if (code == HC_ACTION && lparam)
{
if (wparam == WM_LBUTTONDOWN)
{
//MOUSEHOOKSTRUCT* mstruct = (MOUSEHOOKSTRUCT*)lparam;
static int i = 0;
std::wstring str = L"mouse down " + std::to_wstring(i++);
SetWindowText(hmain_window, str.c_str());
}
}
return CallNextHookEx(hhook, code, wparam, lparam);
}
int APIENTRY wWinMain(HINSTANCE hinst, HINSTANCE, LPWSTR, int)
{
...
RegisterClassEx(...);
hmain_window = CreateWindow(...);
hhook = SetWindowsHookEx(WH_MOUSE_LL, mouse_proc, hinst, 0);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UnhookWindowsHookEx(hhook);
return 0;
}
You can try SetWindowsHookEx with parameter WH_MOUSE_LL or WH_MOUSE.
This article shows how to install a keyboard hook. You can replace WH_KEYBOARD with WH_MOUSE to install a mouse hook and use this document to handle the callback.

Cant create window using CreateWindowEx function

I cant create the window using code below although i get no error in compilation.Only a window with title of my project name appears.I also set hwnd=NULL after CreateWindowEx invocation to see whether MessageBox works but it does not work too.
#include <windows.h>
#include <StdAfx.h>
const char* myClassName="myWindowsClassName";
//The window procedure
LRESULT CALLBACK WndProc( HWND hwnd , UINT msg , WPARAM wParam , LPARAM lParam){
switch(msg){
case WM_CLOSE:
DestroyWindow( hwnd );
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc( hwnd , msg , wParam , lParam );
}
return 0;
}
//Registering window
int WINAPI WinMain( HINSTANCE hInstance , HINSTANCE hPrevInstance , LPSTR lPCmdLine , int nCmdShow ){
WNDCLASSEX wc;
HWND hwnd;
MSG msg;
wc.cbSize=sizeof( WNDCLASSEX );
wc.style=0;
wc.lpfnWndProc= WndProc;
wc.cbClsExtra=0;
wc.hInstance=hInstance;
wc.hIcon=LoadIcon( NULL , IDI_APPLICATION);
wc.hCursor=LoadCursor(NULL , IDC_ARROW);
wc.hbrBackground= (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName=NULL;
wc.lpszClassName= (LPCWSTR) myClassName;
wc.hIconSm=LoadIcon( NULL , IDI_APPLICATION );
if( !RegisterClassEx( &wc ) ){
MessageBox( NULL ,L"Window registeration failed" ,L"Error!" , MB_ICONEXCLAMATION | MB_OK );
return 0;
}
//Creating the window
hwnd=CreateWindowEx( WS_EX_CLIENTEDGE , (LPCWSTR)myClassName , L"The title of my window" , WS_OVERLAPPEDWINDOW , CW_USEDEFAULT , CW_USEDEFAULT, 320 , 240 , NULL , NULL , hInstance , NULL );
hwnd=NULL;
if( hwnd==NULL ){
MessageBox( NULL ,L"Window creation failed",L"Error!", MB_ICONEXCLAMATION | MB_OK );
return 0;
}
ShowWindow ( hwnd , nCmdShow );
UpdateWindow(hwnd);
// Step 3: The Message Loop
while(GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
Where is the problem?
Thanks
Unicode vs ANSI mismatch?
myClassName is char* but you cast it to (LPCWSTR). If you are compiling as Unicode (and you should) then you should define the class name as const WCHAR* myClassName=L"myWindowsClassName"; and remove the casts (or use const_cast<LPTSTR>().
You also fail to initialize .cbWndExtra. Change WNDCLASSEX wc; to WNDCLASSEX wc = {};
You should perform better error checking to diagnose failures. Check on MSDN to see if a function sets the last error when it fails. If it does, call GetLastError() after the function fails.

can we run our own WNDPROC() from injected dll and control the running exe?

I am trying to run a program which can inject a dll into a running exe and from that dll i want to run a function same as WndProc() to get control of running exe.Basically i want to run GetMessage() of the running exe.
here is my dll injection code.
#include<iostream>
#include<conio.h>
#include<Windows.h>
void main()
{
DWORD procId;
HWND runningWndHandle,dllWnd;
HANDLE hProcess=NULL;
char *myDll=new char[200];
myDll="C:\\Users\\User\\Documents\\Visual Studio 2010\\Projects\\C# learning\\myDll\\Debug\\myDll.dll";
runningWndHandle=FindWindow(NULL,"Form1");
GetWindowThreadProcessId(runningWndHandle,&procId);
//open process with all access
hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,procId);
//allocate some space or memory for dll path
LPVOID DllVirtLoc=VirtualAllocEx(hProcess,0,strlen(myDll),(DWORD)0x1000,(DWORD)0x04);
//write dll path to newly allocated space
WriteProcessMemory(hProcess,DllVirtLoc,myDll,strlen(myDll),NULL);
//call Load library with our dllpath as arg from dummy space
CreateRemoteThread(hProcess,NULL,NULL,(LPTHREAD_START_ROUTINE)GetProcAddress((HMODULE)GetModuleHandle("kernel32.dll"),(LPCSTR)"LoadLibraryA"),(LPVOID)DllVirtLoc,NULL,NULL);
//test connection to Dll
while((dllWnd=FindWindowEx(NULL,NULL,"HOOK from HOME","FIND ME"))==0)
Sleep(250);
PostMessageA(dllWnd,0x1111,0,0);
//create a thread for return messages
system("PAUSE");
return ;
}
this code works properly but the dll is creating some problems.
this is my dll code
// dllmain.cpp : Defines the entry point for the DLL application.
#include <Windows.h>
LRESULT CALLBACK WndProc ( HWND, UINT, WPARAM, LPARAM ) ;
HINSTANCE hInst ;
void func(HINSTANCE hInstance, int nCmdShow, char* pTitle)
{
char classname[ ] = "MyWindowClass" ;
HWND hWnd ;
WNDCLASSEX wcex ;
wcex.cbSize = sizeof ( WNDCLASSEX ) ;
wcex.style = CS_HREDRAW | CS_VREDRAW ;
wcex.lpfnWndProc = ( WNDPROC ) WndProc ;
wcex.cbClsExtra = 0 ;
wcex.cbWndExtra = 0 ;
wcex.hInstance = hInstance ;
wcex.hIcon = NULL ;
wcex.hCursor = LoadCursor ( NULL, IDC_ARROW ) ;
wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 ) ;
wcex.lpszMenuName = NULL ;
wcex.lpszClassName =(LPCWSTR)classname ;
wcex.hIconSm = NULL ;
if ( !RegisterClassEx ( &wcex ) )
return;
hInst = hInstance ; // Store instance handle in our global variable
hWnd = CreateWindow ((LPCWSTR) classname, (LPCWSTR)pTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL,
NULL, hInstance, NULL ) ;
if ( !hWnd )
return ;
ShowWindow ( hWnd, nCmdShow ) ;
UpdateWindow ( hWnd ) ;
MSG msg;
while(GetMessage(&msg,0,0,0))
DispatchMessage(&msg);
return ;
}
LRESULT CALLBACK WndProc ( HWND hWnd, UINT message,WPARAM wParam, LPARAM lParam )
{
switch ( message )
{
case WM_DESTROY :
MessageBox(0,L"I WONT LET YOU CLOSE",L"MESSAGE",0);;
break ;
default :
return DefWindowProc ( hWnd, message, wParam, lParam ) ;
}
return 0 ;
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
if(ul_reason_for_call==DLL_PROCESS_ATTACH)
{
//MessageBox(0,L"HELLo FROM INJECTED CODE",L"MESSAGE ",0);
func((HINSTANCE)hModule,0,"MY WINDOW");
}
}
i want to run the function "func()" and from there want to execute the wndproc() to GetMessages of running exe.Now the PROBLEM is that CreateWindow() is returning an NULL value,and more over it is not going into the WndProc() and it makes the running exe inaccessible(HANG).
Is there any way by which i can run the WNDPROC() and get the messages from running window??
You should not create a window in DllMain, you will risk a deadlock on the loader lock. Some reasons not to do anything scary in your DllMain.
You should call GetLastError right after CreateWindow fails to find out why. It looks like you are compiling the .DLL with UNICODE defined but you are using narrow strings everywhere and casting to LPCWSTR, don't do that! There should be very few casts in your code. Only cast the return value of GetProcAddress in your case. The strings should be prefixed with L or compile everything as ANSI.
There should be plenty of examples of dll injection on Codeprojects and other sites that show how to call a function outside DllMain. The sloppy way is to just use GetExitCodeThread on the first thread after WaitForSingleObject and then create another remote thread because you now have the information needed to calculate the address of func in the remote process (local GetProcAddress - local LoadLibrary + remote LoadLibrary). This article should get you started.
After injection you can subclass the window.

WndProc() is not getting the messages I sent to it

I made a project that creates a DLL. This project uses the WFS methods and they access some hardware (devices) to get information or execute some commands.
In my project, I first open these devices then register them, I later use other methods to get information or execute.
HRESULT extern WINAPI WFSOpen ( LPSTR lpszLogicalName, HAPP hApp, LPSTR lpszAppID, DWORD dwTraceLevel, DWORD dwTimeOut, DWORD dwSrvcVersionsRequired, LPWFSVERSION lpSrvcVersion, LPWFSVERSION lpSPIVersion, LPHSERVICE lphService);
HRESULT extern WINAPI WFSRegister ( HSERVICE hService, DWORD dwEventClass, HWND hWndReg);
As you can see, the WFSRegister requires HWND as a parameter. WFSRegister uses this parameter to send events or messages to it.
My project is not an MFC project and I have no windows. I decided to create a window and assign the correct HWND to WFSRegister. I also created WndProc to get the messages that the WFS methods will send to me later.
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WFS_EXECUTE_EVENT:
cout<<"WFS_EXECUTE_EVENT";
break;
case WFS_SERVICE_EVENT:
cout<<"WFS_EXECUTE_EVENT";
break;
case WFS_USER_EVENT:
cout<<"WFS_USER_EVENT";
break;
case WFS_SYSTEM_EVENT:
cout<<"WFS_SYSTEM_EVENT";
break;
}
return DefWindowProc(hWnd, msg, wParam, lParam );
}
void Init_Window()
{
WNDCLASS Wclass;
Wclass.hInstance = gHinstance;
Wclass.cbClsExtra = 0;
Wclass.cbWndExtra = 0;
Wclass.lpszClassName = TEXT("Device_Manager_Class_Name");
Wclass.lpszMenuName = NULL;
Wclass.lpfnWndProc = WndProc;
Wclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
Wclass.hCursor = LoadIcon(NULL, IDC_ARROW);
Wclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
Wclass.style = CS_OWNDC;
if(!RegisterClass(&Wclass))
{
cout<<"Unable to Register Class";
}
ULONG Window_Width;
ULONG Window_Height;
DWORD style;
Window_Width = SCREEN_WIDTH;
Window_Height = SCREEN_HEIGHT;
style = WS_OVERLAPPED|WS_SYSMENU;
gHwnd = CreateWindow(TEXT("Device_Manager_Class_Name")
, TEXT("Device_Manager_Class_Title")
, style
, 0
, 0
, Window_Width
, Window_Height
, GetDesktopWindow()
, NULL
, gHinstance
, NULL);
if(!gHwnd){
cout<<"Unable to create the main window";
}
ShowWindow(gHwnd, SW_SHOW);
UpdateWindow(gHwnd);
SetFocus(gHwnd);
}
Init_Window() Successfully create window, I have no prob here.
When I want to register my device, I call the following code to get the correct HWND:
HWND windows_handle = FindWindow(TEXT("Device_Manager_Class_Name"), 0);
HRESULT result = WFSRegister(wfsRes.hService, WFS_EXECUTE_EVENT || WFS_SERVICE_EVENT || WFS_USER_EVENT || WFS_SYSTEM_EVENT , windows_handle);
result is S_OK(meaning the device registered successfully) and windows_handle refers to the same HWND I created in Init_Window(). For example, both have 0x00100a58 values.
Now I change some property on my devices and I expect to get these message on my WndProc(), but it's not working.
WndProc() working somehow and gets some messages, but not the ones I want (not the ones the devices send to it).
I'm sure the devices send message (as events) because I can see they do by reading their logs.
For example:
2013/09/25 16:46:29 HService : 44 Event WFS_SRVE_SIU_PORT_STATUS Sent for HWND = 330d1c hResult = WFS_SUCCESS
HWND in the log refers to same HWND I created in Init_Window() and windows_handle.
Also, you all got what I want to do. If you have any other solution please feel free to mention it.
I found solution thanks to dear Igor Tandetnik
All i needed to do is to add GetMessage()
MSG msg;
BOOL bRet;
HWND windows_handle = FindWindow(TEXT("Device_Manager_Class_Name"), 0);
while( (bRet = GetMessage( &msg, windows_handle, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg); //<< This line send msg to WndProc()
}
}

CreateWindowEx function fails but GetLastError() returns ERROR_SUCCESS

I am trying to create a simple window with C/C++ using the native Windows message queue system (without .NET). I followed the MSDN tutorial and wrote some basic code that creates an empty window:
void main()
{
HINSTANCE hinst;
HWND hwndMain;
WNDCLASSEX wnd;
MSG msg;
hinst = GetModuleHandle( NULL );
memset( &wnd, 0, sizeof( wnd ) );
wnd.cbSize = sizeof( wnd );
wnd.lpszClassName = "MainWClass";
wnd.lpfnWndProc = MainWProc;
wnd.hInstance = hinst;
int result = RegisterClassEx( &wnd );
if( !result )
{
printf("RegisterClassEx error: %d\r\n", GetLastError() );
}
hwndMain = CreateWindowEx
(
0, //extended styles
wnd.lpszClassName, //class name
"Main Window", //window name
WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL | WS_MINIMIZEBOX, //style tags
CW_USEDEFAULT, //horizontal position
CW_USEDEFAULT, //vertical position
CW_USEDEFAULT, //width
CW_USEDEFAULT, //height
(HWND) NULL, //parent window
(HMENU) NULL, //class menu
(HINSTANCE) wnd.hInstance, //some HINSTANCE pointer
NULL //Create Window Data?
);
if( !hwndMain )
{
printf("Oh shi- %d\n", GetLastError() );
}
ShowWindow( hwndMain, SW_SHOWDEFAULT );
UpdateWindow( hwndMain );
}
When I run/debug the program, CreateWindowEx returns 0 which means it failed. This triggers the error message "Oh shi- [error code]". The most confusing part is that the error message prints to console:
Oh shi- 0
The error code returned by GetLastError() is 0, which is ERROR_SUCCESS!
I am at a total loss; what is happening? I am so confuse...
P.S.
I am using Visual C++ Express 2010 on Windows 7 32-bit. I have written a Windows Procedure elsewhere but it simply returns 0 for all cases. If, however, anyone wants to see it, I will be happy to show it.
I have changed the Project Default character set of my Visual C++ project to "Not Set". I should not need to prefix L to my things.
Edit: added wnd.hInstance = hinst;
Edit: removed the unnecessary (WNDPROC) cast
Edit: added error checking for RegisterClassEx
It turns out that the problem was with Visual C++ Express (or at least not with the code itself). I copied the code to another project and it worked.
wnd.lpfnWndProc = (WNDPROC) MainWProc;
We can't see the real reason you need to use the cast but it is very fishy. Windows returns 0 from GetLastError() if it didn't see anything going wrong. Which can happen if the window procedure is broken. Like this one:
LRESULT CALLBACK MainWProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return 0;
}
Windows sends the WM_NCCREATE message to ask for the window to be created. If that message doesn't get processed then there will be no window. And no error. Fix:
LRESULT CALLBACK MainWProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
Tweak as necessary to customize the window. Just make sure that DefWindowProc() gets called for every message that you don't want to handle yourself. And keep Petzold close at hand to avoid the simple mistakes. And lose the cast.
All modern versions of Windows use Unicode internally, and by default, Visual Studio projects #define _UNICODE/UNICODE, which causes your application to link to the Unicode versions of the Windows headers.
When you're compiling an application as Unicode, however, the character (and thus "string") types are different. Instead of char, they're now wchar_t. That means that you have to explicitly declare your string literals as long strings by prefixing them with an L.
Alternatively, the Windows headers hide all of this behind macros, but it's no longer necessary because Windows has been Unicode for a long time and that's very unlikely to change.
Beyond that, you're missing several things in your initialization of the WNDCLASSEX structure, like the hInstance member. These things all have to be set perfectly, or things will fail. As well, the RegisterClass(Ex) and CreateWindow(Ex) functions must be passed the exact same string values corresponding to the name of the window class, otherwise they will assume you're talking about two different things. Typos are not forgiven!
I highly recommend that you use the Visual Studio wizards to create a blank (but working!) project template.
The correct boilerplate code goes something like this:
#include <windows.h>
#include <tchar.h>
// Define these here to minimize typos, or preferably, load them from a
// resource file at the top of the main function
#define MYCLASSNAME TEXT("MainWndClass")
#define MYWINDOWNAME TEXT("Main Window")
// Global variable to keep track of your hInstance
HINSTANCE g_hInstance;
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
// If you don't process any of the messages yourself, you
// must pass them to DefWindowProc for default handling.
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow)
{
// Save the instance handle in a global variable.
g_hInstance = hInstance;
// Register your window class.
// (A full-featured app will probably want to set additional members.)
WNDCLASSEX wcex = {0};
wcex.cbSize = sizeof(wcex);
wcex.lpfnWndProc = WndProc;
wcex.hInstance = hInstance;
wcex.lpszClassName = MYCLASSNAME;
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL, TEXT("Call to RegisterClassEx failed!"), NULL, MB_OK);
return 1;
}
// Create your main window.
HWND hwndMain = CreateWindowEx(0, MYCLASSNAME, MYWINDOWNAME, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL,
hInstance, NULL);
if (!hwndMain)
{
MessageBox(NULL, TEXT("Call to CreateWindowEx failed!"), NULL, MB_OK);
return 1;
}
// Show your main window.
ShowWindow(hwndMain, nCmdShow);
UpdateWindow(hwndMain);
// Run the main message loop.
BOOL bRetVal;
MSG msg;
while ((bRetVal = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (bRetVal == -1)
{
MessageBox(NULL, TEXT("Error encountered in message loop!"), NULL, MB_OK);
return 1;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
I had the same problem.
In my case its just that i used visual sutdio without admin rights.
And i discovered that in this case i cant debug my application.
In debug mode without admin right, CreateWindowEx return null with error code result to 0 like you.
But if you go to your build directory you can use your app (not in debug mode).
So if this the case fro you too, just start visula studio with admin right and its done.
I think there is almost a way to use visual studio debug mode with admin right without start visual stuido with admin password each time. i dont know how to do that, but i think it may be possible.
In my case i had to handle WNC_NCCREATE manually. DefWindowProc returned zero for WNC_NCCREATE, i fixed that with:
LRESULT CALLBACK MainWProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg == WNC_NCCREATE)
return true;
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}