Okay, so I'm having a little trouble with some code. I have a function template:
template<class T1, class T2>
void mainLoop(HDC hDC) {
...*(code)*...
}
and I call it in the function WinMain, as this is a Windows application:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR
lpCmdLine, int nCmdShow) {
void(*mainFunc) (HDC) = &mainLoop;
HWND hwnd = WinCreate(hInstance, hPrevInstance, lpCmdLine, nCmdShow,
mainFunc);
return 0;
}
My error is : "error C2440: 'initializing': cannot convert from 'overloaded-function' to 'void (__cdel *)(HDC)"
I'm working in Visual Studio 2015. I have tried a variety of simple tweaks to the program to make it work, all of which have proved futile efforts. I don't know much about overloading, so that area of c++ is rather new to me. Any help would be appreciated. What can I do to fix this code?
Also note, that when I add
template<class T1, class T2>
before the WinMain function, I get the error "error C2731: 'WinMain' function cannot be overloaded"
Please help.
Related
I'm trying to get my code as perfect as possible, and I've cleaned up all errors and (other) warnings. I'm left with these two:
Warning C28253 Inconsistent annotation for 'WinMain': _Param_(2) has 'SAL_null(__no)' on this instance.
Warning C28252 Inconsistent annotation for 'WinMain': _Param_(2) has 'SAL_null(__maybe)' on the prior instance.
Here is my WinMain function
int CALLBACK WinMain( _In_ HINSTANCE hInstance, _In_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow );
Why is my second paramater HINSTANCE hPrevInstance not annotated correctly despite it being ripped straight from MSDN with the _In_ info?
It is because the hPrevInstance argument actually has the _In_opt_ annotation rather than just _In_.
I have been able to fine the WinMain function. Now I'm trying to make a win32 app:
#include <Windows.h>
int WINAPI WinMain() {
MessageBox(NULL,"Test", "Hello World", NULL);
return 0;
}
and then I get error C2731.
You haven't provided any parameters to the WinMain() method, and the error C2731 is saying that this method cannot be overloaded.
From MSDN:
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow);
Error C2664 is most likely your call to MessageBox, so try changing to something like:
MessageBox(NULL, L"Test", L"Hello World", NULL);
I figured it out I wasn't useint main.cpp as my main source code file and my WinMain needed to be switched to wWinMain
Code:
#include <tchar.h>
#include <windows.h>
typedef INT (WINAPI * lolMessageBoxA)(HWND,LPCSTR,LPCSTR,UINT);
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nCmdShow)
{
lolMessageBoxA UchwytMessageBoxA;
UchwytMessageBoxA = lolMessageBoxA(GetProcAddress(GetModuleHandle("User32.dll"),"MessageBoxA"));
UchwytMessageBoxA(NULL,"TEST WINDOWS","TEXT 2", MB_OKCANCEL | MB_ICONWARNING);
return 0;
}
When i called MessageBoxA normally before making hook the hooking part worked good. But when i erased that part and leaved only the 'hooking' part it fails...
Solved:
#include <tchar.h>
#include <windows.h>
typedef INT (WINAPI * lolMessageBoxA)(HWND,LPCSTR,LPCSTR,UINT);
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nCmdShow)
{
lolMessageBoxA UchwytMessageBoxA;
LoadLibraryA("User32.dll");
UchwytMessageBoxA = lolMessageBoxA(GetProcAddress(GetModuleHandle("User32.dll"),"MessageBoxA"));
UchwytMessageBoxA(NULL,"TEST WINDOWS","TEXT 2", MB_OKCANCEL | MB_ICONWARNING);
return 0;
}
As presented here, there's no reason for the process to have loaded user32.dll. So the call to GetModuleHandle will return NULL. Then the call to GetProcAddress will also fail and return NULL. And well, you can see what happens next.
When you called MessageBoxA directly, the linker would have produced an import table that forced the loader to load user32.dll. But when you removed the call to MessageBoxA, there was no need for it to do so.
You should replace the call to GetModuleHandle with a call to LoadLibrary, and so force the library to be loaded.
Finally, the real reason for you having asked this question is that your code neglects error checking. Don't do that. Check the values returned by the Win32 function calls. Had you done so you would have been able to work this out for yourself.
I upgraded an old project from VC6 to VS2008, and now I get this compile error:
error C2731: 'wWinMain' : function cannot be overloaded
At these lines of code:
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
The same project compiles fine under VC6.
Thanks everyone, I finally found the real culprit, it's a typo, I use LPSTR lpCmdLine instead of LPTSTR lpCmdLine. The real mystery is why it compiled at all under VC6 - it did use wWinMain, but somehow it was OK for lpCmdLine to be char * instead of WCHAR *.
Now I changed it to:
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
And it works under VS2008 too.
Edit: I successfully compiled and even ran the program with this function definition under VC6:
int APIENTRY wWinMain(int *hInstance, float hPrevInstance, int *lpCmdLine, float nCmdShow)
{
MessageBox(0,L"Running.",0,0);
return 0;
}
Interestingly, replacing float nCmdShow to double nCmdShow does give a linker error, I assume because float is 32-bits but double is not.
For me it worked after changing WinMain to wWinMain in VS 2019
I had the same error with a Win32 Console Application. The fix was:
Open Project > Properties ...,
Expand Configuration Properties > Linker > System
Set SubSystem to Not Set
Click OK
I am new to C++, trying to make bootstrapper for an executable. I wanted to send additional parameters along with lpCmdLine
typedef int (__cdecl *BooterMain_t)(HINSTANCE, HINSTANCE, LPSTR, int);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
I load the library
HMODULE Program = LoadLibraryExA(".\\bin\\program.dll", NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
this is how I launch it
BooterMain_t procBooterMain = (BooterMain_t)GetProcAddress(Program,"BooterMain");
procBooterMain(hInstance, hPrevInstance, InternalParameters, nCmdShow);
May I know how to pass InternalParameters along with lpCmdline? Currently it seems to be ignored.
Edit: About Internal Parameters,
char InternalParameters[MAX_PATH] = {0};
_snprintf_s(InternalParameters, _TRUNCATE, "-verify -console");