Thread overview
Win32 RegisterClass Error
Nov 17, 2007
GaboonViper
Nov 17, 2007
Lutger
Nov 17, 2007
GaboonViper
Nov 18, 2007
Stewart Gordon
November 17, 2007
Hi,

I've been working with win32 libraries for a few weeks. I'm trying to build a GUI framework, as I'm not satisfied with the ones currently available.

So currently I'm working on detecting win32 errors and I've found that RegisterClass is giving me an Error Code 2, which apparently translates to "The system cannot find the file specified".

It doesn't really seem to matter what I change. It always gives me the same problem. I'm using the win32 headers from the bindings project on dsource.org. However I tried the std.c.windows.windows with the same results.

Below is the code that reproduces the problem. It's basically a slice of one of the tutorials on dsource.org.

Can anyone tell me what causes this error? And how to fix it?

Boyd.




module main;

import std.string;
import std.c.windows.windows;

static HINSTANCE ghInstance;
static HWND      ghWndMain;

void Win32ErrorCheck(char[] aFunction, char[] aFile, int aLine){
    int fLastError = GetLastError();
    if (fLastError > 0){
        char[256] fMessage;
        /*FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM,
            null, fLastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), fMessage.ptr, 256, null );*/

        throw new Exception(aFile~ "("~toString(aLine)~"): Win32 Error "~toString(fLastError)~" for " ~ aFunction ~ ", ");
    } else {
        //ShowMessage(aFunction ~ " succeeded");
    }
}

void DoMessagePump()
{
  MSG msg;
  while (GetMessageA(&msg, cast(HWND) null, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessageA(&msg);
  }
}

void CreateMainWindow()
{
  HWND hWnd;
  hWnd = CreateWindowA("DWndClass",
               "MiniCalc",
               WS_THICKFRAME | WS_MAXIMIZEBOX
               | WS_MINIMIZEBOX | WS_SYSMENU | WS_VISIBLE,
               CW_USEDEFAULT, CW_USEDEFAULT,
               125, 150, HWND_DESKTOP,
               cast(HMENU) null, ghInstance, null);
  assert(hWnd);
  ghWndMain = hWnd;
}

void InitApplication()
{
  WNDCLASS wc;
  wc.lpszClassName = "DWndClass";
  wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
  wc.lpfnWndProc = &WindowProc;
  wc.hInstance = ghInstance;
  wc.hIcon = LoadIconA(cast(HINSTANCE) null, IDI_APPLICATION);
  wc.hCursor = LoadCursorA(cast(HINSTANCE) null, IDC_CROSS);
  wc.hbrBackground = cast(HBRUSH) (COLOR_WINDOW + 1);
  wc.lpszMenuName = null;
  wc.cbClsExtra = wc.cbWndExtra = 0;

  assert(RegisterClassA(&wc));
  Win32ErrorCheck("RegisterClassA", __FILE__, __LINE__);
}

void InitInstance()
{
  ghInstance = GetModuleHandleA(null);
  InitApplication();

  CreateMainWindow();
}

/**********************************************************/

/* Note the similarity of this code to the console D startup
 * code in \dmd\src\phobos\dmain2.d
 * You'll also need a .def file with at least the following in it:
 *  EXETYPE NT
 *  SUBSYSTEM WINDOWS
 */

extern (C) void gc_init();
extern (C) void gc_term();
extern (C) void _minit();
extern (C) void _moduleCtor();
extern (C) void _moduleUnitTests();

extern (Windows)
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
            LPSTR lpCmdLine, int nCmdShow)
{
  int result = 1;

  gc_init();      // initialize garbage collector
  _minit();     // initialize module constructor table

  try {
    _moduleCtor();    // call module constructors
    _moduleUnitTests(); // run unit tests (optional)

    InitInstance();
    DoMessagePump();
  }
  catch (Object o) {    // catch any uncaught exceptions
    MessageBoxA(null, cast(char *)o.toString(), "Error",
                MB_OK | MB_ICONEXCLAMATION);
    result = 0;   // failed
  }
  gc_term();      // run finalizers; terminate garbage collector
  return result;
}

extern(Windows)
int WindowProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam)
{
  switch (uMsg) {

    case WM_DESTROY:
      PostQuitMessage(0);
      break;

    case WM_NOTIFY:
      break;

    default:
      break;
  }
  return DefWindowProcA(hWnd, uMsg, wParam, lParam);
}
November 17, 2007
GaboonViper wrote:
> Hi,
> 
> I've been working with win32 libraries for a few weeks. I'm trying to build a GUI framework, as I'm not satisfied with the ones currently available.
> 
> So currently I'm working on detecting win32 errors and I've found that RegisterClass is giving me an Error Code 2, which apparently translates to "The system cannot find the file specified".
> 
> It doesn't really seem to matter what I change. It always gives me the same problem. I'm using the win32 headers from the bindings project on dsource.org. However I tried the std.c.windows.windows with the same results.
> 
> Below is the code that reproduces the problem. It's basically a slice of one of the tutorials on dsource.org.
> 
> Can anyone tell me what causes this error? And how to fix it?
> 
> Boyd.

The problem is that there is no problem. If you check the return value of RegisterClass, you'll see that it works fine. The reason you get this error from GetLastError, is because the last error is only defined when an error actually occured. It doesn't tell you if a function executed succesfully.


A note about the message pump from msdn:

<quote>

Warning

Because the return value can be nonzero, zero, or -1, avoid code like this:

while (GetMessage( lpMsg, hWnd, 0, 0)) ...

The possibility of a -1 return value means that such code can lead to fatal application errors. Instead, use code like this:

BOOL bRet;

while( (bRet = GetMessage( &msg, hWnd, 0, 0 )) != 0)
{
    if (bRet == -1)
    {
        // handle the error and possibly exit
    }
    else
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

</quote>
November 17, 2007
Of course!

Thanks, this stupid problem had my brain whacked for hours:/ Sometimes it's the obvious that we can't figure out.

As for the messagepump thing. I'm not actually using the code I posted, except to figure out that one problem. I don't handle messages with a result <= 0. Though I don't actually raise an error message either, so I'm glad for this reminder.

Thanks again,
Boyd.

---------
On Sat, 17 Nov 2007 13:31:13 +0100, Lutger <lutger.blijdestijn@gmail.com> wrote:

> GaboonViper wrote:
>> Hi,
>>  I've been working with win32 libraries for a few weeks. I'm trying to build a GUI framework, as I'm not satisfied with the ones currently available.
>>  So currently I'm working on detecting win32 errors and I've found that RegisterClass is giving me an Error Code 2, which apparently translates to "The system cannot find the file specified".
>>  It doesn't really seem to matter what I change. It always gives me the same problem. I'm using the win32 headers from the bindings project on dsource.org. However I tried the std.c.windows.windows with the same results.
>>  Below is the code that reproduces the problem. It's basically a slice of one of the tutorials on dsource.org.
>>  Can anyone tell me what causes this error? And how to fix it?
>>  Boyd.
>
> The problem is that there is no problem. If you check the return value of RegisterClass, you'll see that it works fine. The reason you get this error from GetLastError, is because the last error is only defined when an error actually occured. It doesn't tell you if a function executed succesfully.
>
>
> A note about the message pump from msdn:
>
> <quote>
>
> Warning
>
> Because the return value can be nonzero, zero, or -1, avoid code like this:
>
> while (GetMessage( lpMsg, hWnd, 0, 0)) ...
>
> The possibility of a -1 return value means that such code can lead to fatal application errors. Instead, use code like this:
>
> BOOL bRet;
>
> while( (bRet = GetMessage( &msg, hWnd, 0, 0 )) != 0)
> {
>      if (bRet == -1)
>      {
>          // handle the error and possibly exit
>      }
>      else
>      {
>          TranslateMessage(&msg);
>          DispatchMessage(&msg);
>      }
> }
>
> </quote>
November 18, 2007
"GaboonViper" <gaboonviper@gmx.net> wrote in message news:op.t1xpyxi8th8wtu@gabonica.home.nl...
<snip>
> void InitApplication()
> {
>    WNDCLASS wc;
>    wc.lpszClassName = "DWndClass";
>    wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
>    wc.lpfnWndProc = &WindowProc;
>    wc.hInstance = ghInstance;
>    wc.hIcon = LoadIconA(cast(HINSTANCE) null, IDI_APPLICATION);
>    wc.hCursor = LoadCursorA(cast(HINSTANCE) null, IDC_CROSS);
>    wc.hbrBackground = cast(HBRUSH) (COLOR_WINDOW + 1);
>    wc.lpszMenuName = null;
>    wc.cbClsExtra = wc.cbWndExtra = 0;
>
>    assert(RegisterClassA(&wc));

Your code is broken here.  If compiling in release mode, assert expressions are not evaluated, and so your window class won't be registered.

Moreover, because RegisterClass (like many Windows API functions) returns zero on failure, the failure of the assert would render the following statement useless:

>    Win32ErrorCheck("RegisterClassA", __FILE__, __LINE__);
> }
<snip>

Simplest fix:

   if (!RegisterClassA(&wc)) {
       Win32ErrorCheck("RegisterClassA", __FILE__, __LINE__);
   }

Stewart.

-- 
My e-mail address is valid but not my primary mailbox.  Please keep replies on the 'group where everybody may benefit.