C++ - Basic WinAPI question - c++

I am now working on a some sort of a game engine and I had an idea to put everything engine-related into a static library and then link it to my actual problem.
Right now I achieved it and actually link that library and every functions seem to work fine, except those, which are windows-related.
I have a chunk of code in my library that looks like this:
hWnd = CreateWindow(className, "Name", WS_OVERLAPPED | WS_CAPTION | WS_EX_TOPMOST,
0, 0,
800, 600,
NULL, NULL, GetModuleHandle(NULL), this);
if (hWnd) {
ShowWindow(hWnd, SW_NORMAL);
UpdateWindow(hWnd);
} else {
MessageBox(NULL, "Internal program error", "Error", MB_OK | MB_ICONERROR);
return;
}
When this code was not in the library, but in the actual project, it worked fine, created the window and everything was ok. Right now (when I'm linking to my library that contains this code) CreateWindow(...) call returns NULL and GetLastError() returns "Operation succesfully completed" (wtf?).
Could anybody help me with this? Is it possible to create a window and display it using a static library call and why could my code fail?
Thank you.

Ah, maybe you've run into this problem described in an MSDN blog:
If you're writing a static library, you may have need to access the HINSTANCE of the module that you have been linked into. You could require that the module that links you in pass the HINSTANCE to a special initialization function, but odds are that people will forget to do this.
If you are using a Microsoft linker, you can take advantage of a pseudovariable which the linker provides.
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
The pseudovariable __ImageBase represents the DOS header of the module, which happens to be what a Win32 module begins with. In other words, it's the base address of the module. And the module base address is the same as its HINSTANCE.
So there's your HINSTANCE.
So, instead of passing GetModuleHandle(NULL) to CreateWindow, try ((HINSTANCE)&__ImageBase) (make sure it is declared as shown in the blog first).
Edit:
From the comments in that blog entry, one mentions the use of GetModuleHandleEx(), perhaps this is a more Compiler/Linker-agnostic approach.

Related

LoadImageW returns null c++ win32

I started making a simple c++ Win32 program. I was simply trying to load an Image into a window, but it didn't really work. I was debugging for some time, and I know that the problem is that my LoadImageW() function returns null. Code:
void loadImages() {
hPic1 = (HBITMAP)LoadImageW(NULL, L"pic.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
if (hPic1== NULL) {
MessageBox(NULL, L"Error", L"LoadImage error", MB_OK);
}
}
The .bmp file is in the same directory with the .cpp file, and I even tried with the whole path but it didn't work. I get no errors and the main window loads correctly, but the image doesn't display and the message box appears. The loadImages() function gets called at WM_CREATE of the window. The SendMessageW() function looks like this:
SendMessageW(hImageWindow, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hPic1);
Any help is appreciated, and have a nice day!
After calling LoadImageW or any win api function that leads to unexpected result! check documentation in MADN especially "Remarks" section!
Based on documentation may be it is good to call GetLastError()! By checking error code you find the problem, such as "file not found", access privilege error and etc.
You can find description of each error code returned by GetLastError() in page https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes or check by visual studio IDE in Tools-> Error lookup menu!

C++ Creating Window in other cpp files (not in WinMain)

I have a function that is located in a different cpp file than WinMain is, and when called will create a window. However the windows class for that new window was declared and registered inside of WinMain. Now, when I create the window in the separate function, I am forced to redeclare the 2nd and 3rd variable of the CreateWindowEx function:
_In_opt_ LPCTSTR lpClassName,
_In_opt_ LPCTSTR lpWindowName,
because the location of the function that is actually doing the creating doesn't have access to those variables that were created in WinMain. Now... my doubt is, is my program actually using the window class I registered in WinMain? For all I know, redeclaring these variables, and creating the function far away from the WinMain function could have caused the compiler to adopt some other standard window class. So, is my program actually using the window class I registered in WinMain?
Edited: giving slightly more code
//+++++++++++++++++++++++++++++++++++++cpp file with win main:
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
...//previous code made the main window of the program and so forth
const char g_szClassName2[] = "windowClass2";//name of the window class
WNDCLASSEX winClass2;
HWND invisHWnd;
winClass2.cbSize = sizeof(WNDCLASSEX);
winClass2.style = 0;
winClass2.lpfnWndProc = WndProcedure2;
winClass2.cbClsExtra = 0;
winClass2.cbWndExtra = 0;
winClass2.hInstance = hInstance;
winClass2.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winClass2.hCursor = LoadCursor(NULL, IDC_ARROW);
winClass2.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
winClass2.lpszMenuName = NULL;
winClass2.lpszClassName = g_szClassName2;
winClass2.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&winClass2);
... //other code irrelevant to issue
}
//+++++++++++++++++++++++++++++++++++++other cpp file:
void otherCppFile::creatingWindow()
{
const char g_szClassName2[] = "windowClass2";//name of the window class
const char WndName2[] = "winClass2";//name of the window class
HWND windowHandle = CreateWindowEx(0,
g_szClassName2,
WndName2,
WS_OVERLAPPEDWINDOW,
0,
0,
800,
500,
NULL,
NULL,
NULL,
NULL);
}
Is this last function using the window class registered in WinMain even though it is not located in WinMain and some of the variables are redeclared in the function?
The whole point of registering a window class is so that it is unique and you can use it whenever you need to. When you register a window class using the RegisterClass[Ex] function, you have two options for identifying it:
The window class name (a string) that you passed into the function.
An ATOM (an integer value) that is returned by the function.
In 99.9% of cases, you'll forget about the ATOM and just use the string. You need the string to create the window class, so you might as well just keep up with the string and use it to create windows of that class.
Technically, what you're doing is okay, then. You have multiple variables, but they all contain exactly the same string value, so everything is working properly. But that's a maintenance nightmare, and also violates the DRY (don't repeat yourself) rule. What if you wanted to change the name of your window class? You'd have to find every file that declared it and make sure that you updated it. Then you'd have to wait forever for your entire project to recompile, because you've touched large numbers of files. No good.
Instead, you want to declare this variable at global scope, making it available in every file of your project that creates windows. Put it in a common header file that you're going to include in all of your code files, or make a separate Window.h header or something of that nature and include it where appropriate.
Do make sure that this window class name is declared as a constant. There is no reason it should ever be modified during the execution of your application.
If you're struggling with declaring and/or using global constants in C++, you might check the answers to this question or do a search of your own on Stack Overflow. This part is not unique to Windows programming; it is just basic C++.
Of course, you'll often hear that global variables are bad. That's true enough. The code that you're writing isn't really C++. It is C. The Windows API is a C API, so it naturally leads you into writing C code in C++. If you want to really write C++ code, you'll need to find (or write your own) C++ wrapper around the C-based Windows API. For example, you'd write a class that represents windows, and that class would contain a static class-level constant that holds the name of your window class. The class would be responsible for creating all new windows, so you wouldn't need to scatter that information or those implementation details across multiple code files.
As far as the window name, this is completely different. Windows doesn't use it to identify your window. In fact, it is a completely optional parameter for the CreateWindow[Ex] function. You don't even have to give the window a name. This is actually the name that appears in the window's title bar. It is used by the user to identify the window. As such, it often needs to be localized and should be stored in your project's resources file, not in the source code. Use the LoadString function to load strings from your project's resource file. You can do this dynamically whenever you create a window: just load the string you want to use as the caption for that particular window.

GetModuleHandle(NULL) vs hInstance

When programming using the Windows API, I've always made the HINSTANCE from WinMain a global variable immediately. If I want to make an OK button, I'd do it like so (given global HINSTANCE g_hInstance):
return CreateWindow("BUTTON", "OK", WS_TABSTOP|WS_VISIBLE|WS_CHILD|BS_DEFPUSHBUTTON, 10, 10, 100, 30, exampleParentWindow, EXAMPLECHILDID, g_hInstance, NULL);
but lately I've been seeing the instance handle determined without having to be passed as a parameter or clogging up the global namespace, using a call to GetModuleHandle(NULL)*. So, the example above would look like this:
return CreateWindow("BUTTON", "OK", WS_TABSTOP|WS_VISIBLE|WS_CHILD|BS_DEFPUSHBUTTON, 10, 10, 100, 30, exampleParentWindow, EXAMPLECHILDID, GetModuleHandle(NULL), NULL);
*If your compiler supports it, you can write GetModuleHandle(nullptr) and the statement will have the same result.
What's the advantage (if any) of calling GetModuleHandle(NULL) over explicitly specifying the instance handle?
Fine Print: I know this has an answer, but it has not been phrased as its own question on StackOverflow.
In an EXE, it does not make any difference. hInstance from WinMain() and GetModuleHandle(NULL) both refer to the same HINSTANCE (the module of the .exe file). But it does make a difference if you are creating windows inside of a DLL instead, since you have to use the DLL's hInstance but GetModuleHandle(NULL) will still return the HINSTANCE of the EXE that loaded the DLL.
HMODULE WINAPI GetModuleHandle( _In_opt_ LPCTSTR lpModuleName );
Give the module handle of the module name passed.If you are passing NULL, the you get the module handle of the EXE which is currently running.
If you specifically name the module name, you get the module handle of that dll which is mapped to the process address space.
The use is that when you are trying to call a function exported by the dll, or trying to use a dialog template in side that dll.At that time if you use the HMODULE returned form GetMoudleHandle(NULL) your code wont work.
Just to add my two-cents to these answers. In case you need to get the module handle from within a DLL (and don't want to, or can't save it in a global variable from the DllMain call) you can use this function to get it instead:
HMODULE getThisModuleHandle()
{
//Returns module handle where this function is running in: EXE or DLL
HMODULE hModule = NULL;
::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
(LPCTSTR)getThisModuleHandle, &hModule);
return hModule;
}
One potential gain you get from using GetModuleHandle(NULL) over directly using the WinMain HINSTANCE comes more from architecture. If you want to provide a platform-independent system that runs on linux/windows/whatever you can have a layer that does platform-dependent translations. If that's the case you don't want platform dependent objects such as HINSTANCE showing up in the main application code. So, to circumvent that platform-dependence I put GetModuleHandle(NULL) in the constructor of the platform-dependent class which has the same effect that direct use of the WinMain HINSTANCE does but that abstracts that specific functionality out of the main codebase itself.

How to get detail error info from E_FAIL?

When I use ATL in MFC Application(Don't ask me why, just because I like), sometimes I got the error code: E_FAIL. However, it's almost useless for me to locate the specific reason.
I have googled so many times, but found nothing related. I thought there should be something like try{} catch{} in ATL.
Here's some sample code:
CAxWindow m_wndView; // ActiveX host window class.
CComPtr<IWMPPlayer> m_spWMPPlayer; // Smart pointer to IWMPPlayer interface.
AtlAxWinInit();
CComPtr<IAxWinHostWindow> spHost;
HRESULT hr;
CRect rcClient;
GetClientRect(&rcClient);
m_wndView.Create(m_hWnd, rcClient, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN, WS_EX_CLIENTEDGE);
//when I switch to Static Link to ATL from Dynamic Link to ATL, I always get E_FAIL
hr = m_wndView.QueryHost(&spHost);
Anyone can help me?
The error code is entirely function specific. Think of piece of code [on the other side] that does return E_FAIL; What additional detail one can get from it? Chances are high you have no detail at all.
Sometimes you can obtain additional information using GetErrorInfo API which in your case - having your code snippet in mind - is unlikely.
The best you can do is to step inside to reach as close as possible to the origin of the code in order to tell where it comes from.
Use the _com_error class.
Construct an object of this class by passing in the HRESULT value and then use its WCode or ErrorMessage methods to get the error code mapped to the HRESULT value.

Winapi: createWindow in plugin

I'm developing a plugin (a dll that is loaded by other app). There's a special function that should return HWND so that app can show a dialog. The problem is that I don't know from where I can get the hInstance (it's not passed as a parameter to the function).
Looks like I'm not understanding something, I'm new to all this stuff, so forgive if the question is silly.
UPD: tried to get hInstance with getModuleHandle:
void* createLoginDialog() {
HINSTANCE hIns = (HINSTANCE) GetModuleHandle(L"comapping");
HWND hWnd = CreateWindow(L"Popup",
L"Enter login",
WS_POPUP,
20,
20,
20,
20,
NULL,
NULL,
hIns,
NULL);
return hWnd;
}
I'm still getting Access Violation.
Several ways to get it:
The first argument passed to your DllMain() entrypoint, cast to HINSTANCE
GetModuleHandle() using your DLL name, cast to HINSTANCE
VirtualQuery(), passing the address of your function. Cast the returned MEMORY_BASIC_INFORMATION.BaseAddress to HINSTANCE. Works on both 32-bit and 64-bit versions of Windows.
According to the documentation of CreateWindow, the hInstance argument is optional. This means that it's valid to pass NULL here. However, as Simon Richter points out in the comments to this answer, the argument may only be NULL the window class is registered globally.
If you're writing a DLL, you may just as well define a DllMain entry point function yourself. This function is called by Windows, passing the handle of your function as the first arugment. You can memorize this handle somewhere to reuse it when creating your window.