Hi there,
There's a few little annoying things I have been trying to figure out involving the Win32 API lately (in C/C++):
1) All of the tutorials I have read involving programming games for Windows have global HINSTANCE and HWND objects declared at run time. Is this really necessary? Is there a way for me to disclude these variables, ie a function I can use to access them when I need them?
2) When I try and code an object oriented window model, I can't set the window object's window class's lpfnWndProc value to the WndProc function, whether or not it is a class member function or a normal function. How can I give a window class it's own WndProc function for message handling?
I'm also wondering about a few other non-Windows thingies:
3) In C++, I need to extern literally every global variable in each new source code file I make, otherwise the compiler complains about them being already declared or something. I'm used to using C where I can list all of my global variables in the program's main header file (compiling with GCC). Is there a simple way that I can just simply declare a global variable in the program's main header file that doesn't have an effect on performance? I don't like having to type at least two or more things every time I create a new global object, I'd rather just type it once.
4) I don't like how C++ handles C strings, ie making them const and such, and I think the std string is too slow for my needs. I've tried a few work arounds but the program crashes when I try and access/modify a C string in code that I've converted over from C. Are there any fast alternatives or libraries to the std string object? Speed is very important in this regard.
You don't need to answer all of these, if you know something about one, shoot.
Thanks!
- Sig
A few Win32 API questions
1. No it's not necessary. For HINSTANCE though there's really no reason not to make it global since it's a fixed value for the lifetime of the module. If you really want avoid making it global you can use GetModuleHandleEx to retrieve it. I've never made a global HWND. Most tutorials do this for simplicity. Most tutorials are not exactly bastions of high-quality coding conventions either.
2. Window procs have to be marked as static if you want them to be a member function. There are eleventy billion examples of this on google.
3. In your header put 'extern Whatever foo;'. In one of your other files (not a header) put 'Whatever foo;'. The former lets everybody know that foo exists somewhere. The latter actually makes it. This seperation has no effect no performance. If you're determined to by lazy there are compiler-specific directives, I don't know the gcc way offhand, in MSVC it's __declspec(selectany).
4. It's very unlikely that std::string will be worse than your handwritten string manipulation code. Use it until you can prove otherwise. "I heard it's slow" isn't valid. If you need to modify C style string then strcpy it to a buffer before you start partying on it.
2. Window procs have to be marked as static if you want them to be a member function. There are eleventy billion examples of this on google.
3. In your header put 'extern Whatever foo;'. In one of your other files (not a header) put 'Whatever foo;'. The former lets everybody know that foo exists somewhere. The latter actually makes it. This seperation has no effect no performance. If you're determined to by lazy there are compiler-specific directives, I don't know the gcc way offhand, in MSVC it's __declspec(selectany).
4. It's very unlikely that std::string will be worse than your handwritten string manipulation code. Use it until you can prove otherwise. "I heard it's slow" isn't valid. If you need to modify C style string then strcpy it to a buffer before you start partying on it.
1) Concur with poster above.
2) What happens? Does the class fail to register or do you get a compiler error?
3)I think if you have a header that's shared across all your modules like say...
"Globals.h" ... and you put all your externs in that header, and include that header in all your modules, it should work. As long as that variable is defined in one of the modules.
Or you could have a struct/class "Globals" and have all the global variables as public static members of that class. That's a common route. Though you'd still have to include the header for this class in all the modules.
4) C style strings will get problematic in C++ eventually, as I've come to find out. I concur with using std::string. There are a few 3rd party cross platform libraries that have similar functionality but I don't know if they'd perform any differently.
2) What happens? Does the class fail to register or do you get a compiler error?
3)I think if you have a header that's shared across all your modules like say...
"Globals.h" ... and you put all your externs in that header, and include that header in all your modules, it should work. As long as that variable is defined in one of the modules.
Or you could have a struct/class "Globals" and have all the global variables as public static members of that class. That's a common route. Though you'd still have to include the header for this class in all the modules.
4) C style strings will get problematic in C++ eventually, as I've come to find out. I concur with using std::string. There are a few 3rd party cross platform libraries that have similar functionality but I don't know if they'd perform any differently.
Quote:Is there a way for me to disclude these variables, ie a function I can use to access them when I need them?
As Anon Mike says, GetModuleHandle works for HINSTANCE. There isn't, however, a similar global function for retrieving variables like window handles, etc. If you declare a global function to retrieve a variable, why not just make the variable that the function retrieves global without the function call overhead?
It would be possible to declare a single global function that would retrieve one of several variables if that appeals to you more, but that would require some typecasting of return types which could get ugly.
1. Well, you should keep the HINSTANCE. You can always obtain it with a call to ::GetModuleInstance(NULL), but I don't see any reason to not keep a global variable for this. There's only one HINSTANCE to store and quite a few functions request this handle. In addition, this value remains constant through the whole application so it shouldn't cause problems with threads.
As for HWND, it depends. My days of Win32 programming are far, but I'd say that if a window is totally independent from the rest of the program and only answers to its own events, then you don't have to store the HWND since the WndProc callback is called with it. Still, if you have a floating non-modal window in your application, you probably want to be able to identify it so you can show and hide it from your menu or tool bar. There are ways to retrieve a particular window via functions like ::GetActiveWindow() and ::EnumChildWindows() but it's usually quicker to just get the right HWND.
2. Do you mean the window class as object-oriented programming, or the window class that you register at the beginning of a program? If the latter, are you sure your WindowProc has the right signature? The function declaration of any WindowProc callback function NEED to be this:
If it's the former, be aware that you can't parse a function as an instance method of an object because a non-static method call has an hidden parameter: the this pointer. (Not sure about class methods though.) That means that you can't pass a method as a WindowProc callback. Calling events in object-oriented code in Win32 is probably done by a basic WindowProc callback that dispatches messages to the window class who's HWND correspond to the one received by WindowProc.
3. What the other posters have said. Every .cpp file needs to see the extern versions, but the real declarations need to be done only once. This is similar to declaring function prototypes, and the actual function farther.
4. What kind of operation do you need to perform on strings? I don't find std::string particularly slow, but if it is, it is probably because, unlike in C#, those strings are mutable, and if you add more characters then the class has reserved, it needs to re-allocate its data elsewhere. Perhaps you can have better result if you call the reserve() method to allocate enough bytes to hold enough characters.
That said, const char * remains the fastest strings, and, except in the cases I need to modify a variable-length string, I will use const char * or const char [].
As for HWND, it depends. My days of Win32 programming are far, but I'd say that if a window is totally independent from the rest of the program and only answers to its own events, then you don't have to store the HWND since the WndProc callback is called with it. Still, if you have a floating non-modal window in your application, you probably want to be able to identify it so you can show and hide it from your menu or tool bar. There are ways to retrieve a particular window via functions like ::GetActiveWindow() and ::EnumChildWindows() but it's usually quicker to just get the right HWND.
2. Do you mean the window class as object-oriented programming, or the window class that you register at the beginning of a program? If the latter, are you sure your WindowProc has the right signature? The function declaration of any WindowProc callback function NEED to be this:
LRESULT CALLBACK WindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
If it's the former, be aware that you can't parse a function as an instance method of an object because a non-static method call has an hidden parameter: the this pointer. (Not sure about class methods though.) That means that you can't pass a method as a WindowProc callback. Calling events in object-oriented code in Win32 is probably done by a basic WindowProc callback that dispatches messages to the window class who's HWND correspond to the one received by WindowProc.
3. What the other posters have said. Every .cpp file needs to see the extern versions, but the real declarations need to be done only once. This is similar to declaring function prototypes, and the actual function farther.
4. What kind of operation do you need to perform on strings? I don't find std::string particularly slow, but if it is, it is probably because, unlike in C#, those strings are mutable, and if you add more characters then the class has reserved, it needs to re-allocate its data elsewhere. Perhaps you can have better result if you call the reserve() method to allocate enough bytes to hold enough characters.
That said, const char * remains the fastest strings, and, except in the cases I need to modify a variable-length string, I will use const char * or const char [].
Quote:Original post by Sigvatr
There's a few little annoying things I have been trying to figure out involving the Win32 API lately (in C/C++):
1) All of the tutorials I have read involving programming games for Windows have global HINSTANCE and HWND objects declared at run time. Is this really necessary? Is there a way for me to disclude these variables, ie a function I can use to access them when I need them?
Make hInstance a global, or pass it everywhere depending how anti-global you feel the need to be. The hwnd you're talking about is a different story. If you have one window in your program then, yeah, you can make it a global and be done with it, but in nontrivial win32 programs you are going to have more than one window...
Quote:
2) When I try and code an object oriented window model, I can't set the window object's window class's lpfnWndProc value to the WndProc function, whether or not it is a class member function or a normal function. How can I give a window class it's own WndProc function for message handling?
Okay, what you posted is gibberish. Are you saying that what you would like to do is make a window be an object that has a member function as is its WNDPROC?
Quote:
3) In C++, I need to extern literally every global variable in each new source code file I make, otherwise the compiler complains about them being already declared or something. I'm used to using C where I can list all of my global variables in the program's main header file (compiling with GCC). Is there a simple way that I can just simply declare a global variable in the program's main header file that doesn't have an effect on performance?
I don't like having to type at least two or more things every time I create a new global object, I'd rather just type it once.
The simple thing to do is to not use a bunch of globals.
Quote:
4) I don't like how C++ handles C strings, ie making them const and such, and I think the std string is too slow for my needs. I've tried a few work arounds but the program crashes when I try and access/modify a C string in code that I've converted over from C. Are there any fast alternatives or libraries to the std string object? Speed is very important in this regard.
So you've written some program and profiled it and the big problem turns out to be std::string?
[Edited by - jwezorek on August 28, 2010 7:19:52 AM]
Quote:Original post by Sigvatr
2) When I try and code an object oriented window model, I can't set the window object's window class's lpfnWndProc value to the WndProc function, whether or not it is a class member function or a normal function. How can I give a window class it's own WndProc function for message handling?
One way to do it is described here. Basically it describes passing in the this pointer when creating a new window; this will be passed as the lParam of the WM_NCCREATE message. You'll then need to set the user-defined area of the window object, called GWL_USERDATA. On any subsequent invocation of the static message procedure, you can grab the this pointer out of the GWL_USERDATA region (it should be the only thing in there) and then call its member message procedure. Hope that makes sense.
The contents of the whole tutorial can be found here.
Quote:Original post by Sigvatr
1) All of the tutorials I have read involving programming games for Windows have global HINSTANCE and HWND objects declared at run time. Is this really necessary? Is there a way for me to disclude these variables, ie a function I can use to access them when I need them?
No, use FindWindow/FindWindowEx and GetModuleInstance.
Quote:Original post by Sigvatr
2) When I try and code an object oriented window model, I can't set the window object's window class's lpfnWndProc value to the WndProc function, whether or not it is a class member function or a normal function. How can I give a window class it's own WndProc function for message handling?
class CGridCtrl{bool Create(){//window creation codelpfnWndProc = WindowProc;m_hWnd = createwindowEx(...);}static LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam){CGridCtrl* lv = static_cast<CGridCtrl*>(::GetProp( hwnd, _T("grid") ));if(lv) return lv->MemberProc(hwnd, msg, wparam, lparam); return DefWindowProc(hwnd, msg, wparam, lparam);}LRESULT CALLBACK MemberProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){switch (msg){//handle messages heredefault:return DefWindowProc(hWnd, msg, wParam, lParam);}return 0;}void Subclass(){assert(m_hWnd);BOOL ret = ::SetProp(m_hWnd, _T("grid"), reinterpret_cast<HANDLE>(this) );assert(ret);m_oldProc = reinterpret_cast<WNDPROC>(SetWindowLongPtr(m_hWnd, GWLP_WNDPROC, (LONG_PTR)GetWndProc()));}}
Note: If you need messages like WM_CREATE than use lpParam of CreateWindowEx instead of my subclass func above. You just set the lpParam of CreateWindowEx to your class pointer and do what I did in subclass in the WM_CREATE message of static windowproc above.
Quote:Original post by Sigvatr
4) I don't like how C++ handles C strings, ie making them const and such, and I think the std string is too slow for my needs.
Debug or Release? Because debug will always be a lil slow due to added error checking. Either way, you could always just use a vector + #include <algorithm> functions.
If you give a sample of what your trying to do with the strings class I will see if I can give you suggestions to make it faster.
Cheers,
Jacob Jingle
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement