Jump to content
  • Advertisement
Sign in to follow this  
CaspianB

Oddities with wstringstream and Win32 CreateWindow

This topic is 3270 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

So, I have the following windows program in which the CreateWindowEx call fails. The code below is stripped out of a wrapper class to illustrate the problem. At first, the CreateWindow method only seemed to be failing if I created an array of strings prior to the initWindow() call. Now, the CreateWindow call always fails if I use the "winClassNameBuf.str().c_str()" to assign the window class name string to the windows class structure. If I use the wstring object (the commented out line which assigns to the winClass.lpszClassName attribute), it succeeds without a problem. My question is, is this just a bug with Visual Studio or is something weird going on in the strings library I'm just not aware of?
#define WIN32_LEAN_AND_MEAN
#include <iostream>
#include <string>
#include <sstream>
#include <windows.h>
#include <windowsx.h>
using namespace std;

HWND hWnd;
HDC hDC;
const int screenWidth = 800;
const int screenHeight = 600;

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
   switch(msg)
   {
      case WM_CLOSE: PostQuitMessage(0); break;
   }
   return ( DefWindowProc(hwnd, msg, wParam, lParam) );
}

bool handleMessages()
{
   MSG msg;
   if ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
   {
      if (msg.message == WM_QUIT) return true;
      TranslateMessage(&msg);
      DispatchMessage(&msg);
   }
   return false;
}

void initWindow()
{
   HINSTANCE hInstance = ::GetModuleHandle(NULL);

   wstringstream winClassNameBuf;
   winClassNameBuf << L"WINDOW" << 1;
   wstring winClassName = winClassNameBuf.str();
   
   WNDCLASSEX winClass;
   winClass.cbSize        = sizeof(WNDCLASSEX);
   winClass.style         = CS_OWNDC | CS_DBLCLKS;
   winClass.lpfnWndProc   = WndProc;
   winClass.cbClsExtra    = 0;
   winClass.cbWndExtra    = 0;
   winClass.hInstance     = hInstance;
   winClass.hIcon         = ::LoadIcon(NULL, IDI_APPLICATION);
   winClass.hCursor       = ::LoadCursor(NULL, IDC_ARROW);
   winClass.hbrBackground = (HBRUSH) ::GetStockObject(BLACK_BRUSH);
   winClass.lpszMenuName  = NULL;
   winClass.lpszClassName = winClassNameBuf.str().c_str();
   //winClass.lpszClassName = winClassName.c_str(); // ################################### Uncomment this line and the CreateWindow method succeeds
   winClass.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

   if ( !::RegisterClassEx(&winClass) )
   {
      ::MessageBox(NULL, L"An error occurred registering the window.", L"", MB_OK);
      return;
   }

   hWnd = ::CreateWindowEx(NULL, winClassNameBuf.str().c_str(), L"EasyGDI Window", 
                        WS_VISIBLE | WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX,
                        100, 100, screenWidth, screenHeight, NULL, NULL, hInstance, NULL);

   if ( !hWnd )
   {
      ::MessageBox(NULL, L"An error occurred creating the window.", L"", MB_OK);
      return;
   }

   hDC = ::GetDC(hWnd);
}

int main()
{
   initWindow();
   
   while ( handleMessages() == false )
   {
   }
   
   return 0;
}

Share this post


Link to post
Share on other sites
Advertisement
There are two major errors.

The first is that the string returned from wstringstream::str() is returned by value, which means that you are acting on a temporary wstring.

The second is that the pointer returned from wstring::c_str() is only guaranteed valid as long as no non-const member function is called on the wstring object and only as long as the wstring is in scope.

In this case, the wstring immediately is destroyed and the wchar_t const* will be invalidated. This also explains why your temporary variable does the right thing.

With it you satisfy both preconditions, both the one that you call no non-const member functions, and the one that the string is still alive.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!