C++ alias for global namespace - c++

I use Visual Studio to create programs in C++ for Windows. I wonder what the best method is to write Windows API functions (including macros) as if they were part of a namespace, e.g. WinAPI. I used to define a macro that is empty, so the preprocessor deletes it, and only the :: will stay in the code, which means global scope:
#define WinAPI
BOOL bResult = WinAPI::SetWindowText( hwnd, L"Test Text" );
// After preprocessing:
BOOL bResult = ::SetWindowText( hwnd, L"Test Text" );
However, I ran into problems with macros, like ListBox_AddString; moreover I don't think that my solution was neat.
I would like to see at first glance whether a function call is part of Windows API, or one of my functions with a similar name. Is there a solution which uses namespaces somehow instead of an empty macro?
Update
I tried to implement Richard Hodges' proposal (using Visual Studio 2010):
namespace MyNamespace
{
int APIENTRY wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR szCmdLine, int iShowCmd )
//...
}
First I received LNK1561: entry point must be defined, so I set Project Properties > Linker > Linker > Advanced > Entry Point = MyNamespace::wWinMain
Then I received LNK1221: a subsystem can't be inferred and must be defined, so I set Project Properties > Linker > Linker > System > SubSystem = Windows (/SUBSYSTEM:WINDOWS)
Now it compiles, links and runs, but iShowCmd is 0x7efde000 (a value I cannot interpret) instead of the usual (SW_SHOW = 0x00000001).
What is wrong?

I think you'll find that it's more productive to put all your application's classes and functions in an app namespace, and treat the global namespace as belonging to the 'current system environment'.
The global namespace is always already polluted with c libraries, windows, posix, OSX, etc.
You can't avoid that, since there are no operating systems with only a c++ API.

Related

Running C++ DLL with rundll32 - Missing entry

So I'm trying to use rundll to test and run my C++ written DLL , and i've followed the guidelines here and on other sites and the entry point looks like this:
__declspec(dllexport) void CALLBACK entry(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
{
//do stuff
}
But the rundll process prompts me with an error message box saying "Error in C:\path\to\DLL Missing entry: entry"
Attempted execution command: "rundll32 C:\path\to\DLL, entry".
You can double-check by running Dumpbin.exe /exports on your DLL to see the actual exported name. Which right now is not entry, as the error message tells you.
You need to prefix extern "C" to the declaration to disable C++ name mangling.
Good enough for a 64-bit executable, but that turns it into _entry#16 if this is a 32-bit DLL, still not quite good enough to keep rundll32 happy. Use Project + Add New Item, Code node, pick the "Module-Definition File (.def)" item template. And make it look like this:
EXPORTS
entry = entry

Why is it CString::LoadString works in the main module(.exe) of my app but will not work in my extensionDLL?

I have this MFC app that loads strings from string resource using CString::LoadString function. Each of the apps dialogue box's classes and its associated resources are contained in an MFC extension DLL.
CString::LoadString loads strings from the main module's(.exe) resource's string resource successfully but fails to load string from the DLL's resource's string resource.
In each case I get my instance handle for load string from CWinApp object by calling :
CWinApp *WinApp = AfxGetApp(),
and of course the instance's handle is WinApp->m_hInstance which I use as the first argument in my call to CString::LoadString function.
What could be the cause and what could be the solution.
Are you passing the EXE's HINSTANCE to load a string from the extension library? Sounds like it.
With MFC, if you have extension libraries and you make sure your string identifiers are unique, you just need to call the CString::LoadString(UINT nID) version. Because extension libraries create CDynLinkLibrary structures that go into a global linked list, the LoadString(UINT) function will search through all your MFC libraries until it finds the HINSTANCE that contains that string, and then it will load from there. If you insist on using the LoadString() function with an HINSTANCE argument, be sure to use the HINSTANCE of the extension DLL, and not the extension of the EXE when you want to load a string or dialog from the DLL.
For small projects, like less than a dozen DLLs, you probably manage to just use unique IDs for everything. When you get into the insanely large projects like 100+ DLLs, then you have to use other techniques like specially named functions in your DLL that call AfxSetResourceHandle() or know to always use the HINSTANCE of the DLL. That's another topic.
Just to complement Joe Willcoxson's answer, be sure to check that every MFC Extension DLL you are using,needs a special initialization code, similar to the example below:
#include "stdafx.h"
#include <afxdllx.h>
static AFX_EXTENSION_MODULE MyExtDLL = { NULL, NULL };
extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
TRACE0("MyExt.DLL Initializing!\n");
// Extension DLL one-time initialization
if (!AfxInitExtensionModule(MyExtDLL, hInstance))
return 0;
new CDynLinkLibrary(MyExtDLL);
}
else if (dwReason == DLL_PROCESS_DETACH)
{
TRACE0("MyExt.DLL Terminating!\n");
// Terminate the library before destructors are called
AfxTermExtensionModule(MyExtDLL);
}
return 1; // ok
}
This code just takes care of CDynLinkLibrary creation, the key to share resources between MFC modules.
If all this are setup correctly -- and without ID clashes -- then it's simply a mather of calling:
CString str;
str.LoadString(IDS_MY_STRING_ID);
anywhere in your code, no matter where the string actually persists.
A good start point on resource IDs and numbering can be found in this link.

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.

Visual C++ Automatically Appending A or W to end of Function

In C++ I have defined a class that has this as a member:
static const std::basic_string<TCHAR> MyClass_;
There is also a getter function for this value:
LPCTSTR CClass::GetMyClassName()
{
return MyClass_.c_str();
}
When I create an instance of this class and then try and access it intellisense pops up but the name has been changed depending on whether the project has been compiled for Unicode or Multibyte. If it has been compiled for Unicode the function appears as:
aClass.GetMyClassNameW();
else it is:
aClass.GetMyClassNameA();
What I'd like to know is how is the name getting changed?
Also I would like to know is it possible for intellisense to show the correct name of the function? So that I can access it like this:
aClass.GetMyClassName()
EDIT: The precise member function name I've used in my code is:
WinClass::GetClassName()
Your method name is literally "GetMyClassName" or is it "GetClassName"?
GetClassName is in the SDK (winuser.h) and is redefined based on the UNICODE defines. If you are using "GetClassName" the intellisense is probably getting confused; in fact the compiler is generating the A/W suffix for the actual compiled method as well but that would all work because everyone (Linker/Compiler) agrees on the redefined name (even if its not visible).
Thats the windows way to support in fact 2 versions of the Win32 API:
One for ascii characters of 1 byte with (char)
One for unicode with chars of typically 2 byte width (wchar)
If you look into i.e. winuser.h, you'll see the following:
WINUSERAPI
BOOL
WINAPI
SetWindowTextA(
__in HWND hWnd,
__in_opt LPCSTR lpString);
WINUSERAPI
BOOL
WINAPI
SetWindowTextW(
__in HWND hWnd,
__in_opt LPCWSTR lpString);
#ifdef UNICODE
#define SetWindowText SetWindowTextW
#else
#define SetWindowText SetWindowTextA
#endif // !UNICODE
I cant exactly tell why the same happens to your function GetMyClassName. But it pobably has the same reason.