CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 15 of 15
  1. #1
    Join Date
    Mar 2003
    Location
    Germany, K-Town
    Posts
    578

    CreateWindowEx(): "Cannot find the file specified"

    Hello,

    Since hours I try to get my code running which is supposed to create a standard window using CreateWindowEx(). However, the returned handle is always NULL.

    I called GetLastError() and received the error string. It reads:

    "The system cannot find the file specified."

    Uh, which file? The only files I'm implicitly dealing with are icon and cursor files. But I use default icons and I checked their handles in the debugger and everything seems to be okay. To be 100% sure I even created my own icons and loaded them using MAKEINTRESOURCE, but nope, still get this confusing error message. I couldn't create an own cursor file, but I tried to use other values like IDC_HAND, but again the same error.

    I think I better post some code now:

    Code:
    HRESULT CMyApp::InitInstance()
    {
    	HRESULT hr = 0;
    
    	WNDCLASSEX wc;
    	ZeroMemory( &wc, sizeof( WNDCLASSEX ) );
    
    	static TCHAR szClassName[] = _T("def_w32_app");
    
    	wc.cbSize		 = sizeof( WNDCLASSEX );
    	wc.hbrBackground = (HBRUSH) GetStockObject( COLOR_WINDOW );
    	wc.hCursor		 = LoadCursor( NULL, IDC_ARROW );
    	wc.hIcon		 = LoadIcon( NULL, IDI_APPLICATION );
    	wc.hIconSm		 = wc.hIcon;
    	wc.lpszMenuName  = NULL;
    	wc.hInstance	 = GetInstance();
    	wc.lpfnWndProc   = ::WindowProc;
    	wc.lpszClassName = szClassName;
    	wc.style		 = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    
    	hr = RegisterClassEx( &wc );
    	if( FAILED( hr ) )
    	{
    		CError e;
    		e.Display();
    
    		return E_FAIL;
    	}
    
    	DWORD dwStyle   = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
    	DWORD dwExStyle = NULL;
    
    	m_hWnd = CreateWindowEx( dwExStyle, szClassName, "Test Window", dwStyle, 100, 100, 800, 600, NULL, NULL, GetInstance(), NULL );
    
    	if( m_hWnd == NULL )
    	{
    		CError e;
    		e.Display();
    
    		return E_FAIL;
    	}
    
    	return S_OK;
    }
    There you go, the whole function as it is now. GetInstance() returns a handle to the instance of the running program. I checked the value, it's okay. The CError class will only call GetLastError() and display a message box. Everything else should be self explanatory.

    Any idea what's going wrong here?
    - Matthias

    "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off." - Bjarne Stroustrup

  2. #2
    Join Date
    Apr 2003
    Posts
    1,755

    Smile

    Youre code seems OK. I just want to know if this code is in DLL. If so, try add the CS_GLOBALCLASS to your wc.style
    Code:
    wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_GLOBALCLASS;
    Hope it will help you

  3. #3
    Join Date
    Mar 2003
    Location
    Germany, K-Town
    Posts
    578
    No, the code is in local *.cpp files.
    - Matthias

    "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off." - Bjarne Stroustrup

  4. #4
    Join Date
    Apr 2003
    Posts
    1,755

    Smile

    When I got a valid HWND and still set the breakpoint to get the last error, I got this error that you are saying. Is this the real code you're working, or you removed some parts between CreateWindowEx and the if statement?

  5. #5
    Join Date
    Mar 2003
    Location
    Germany, K-Town
    Posts
    578
    Nope, it's the full code.

    What exactly did you do to reproduce the error?
    - Matthias

    "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off." - Bjarne Stroustrup

  6. #6
    Join Date
    Mar 2003
    Location
    Germany, K-Town
    Posts
    578
    I don't really know what you mean with "when I got a valid HWND", because I never get a valid HWND.

    m_hWnd is always 0. So something seems to fail during the call of CreateWindowEx.

    Odd is that I pasted in the code from a win32 app created with the wizard, and it still didn't work. The problem must be located elsewhere. Besides, I still don't have a clue why the program complains about a missing file... I mean, WHAT FILE? Is there a way to check which file the error handler is talking about?
    - Matthias

    "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off." - Bjarne Stroustrup

  7. #7
    Join Date
    Mar 2003
    Location
    Germany, K-Town
    Posts
    578
    Haha, it becomes even more odd now:

    I have taken the part of the code from which I thought would cause the trouble and put it in one file, in the WinMain(). And it still doesn't work!

    Here's the code as it is now:

    Code:
    #include <windows.h>
    #include <tchar.h>
    
    //--------------------------------------------------------------------------------------------------
    // METHOD NAME: WindowProc
    // RETURN TYPE: LRESULT 
    // DESCRIPTION: Callback function for handling Windows messages
    //--------------------------------------------------------------------------------------------------
    
    LRESULT CALLBACK WindowProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
    {
    	return 0L;
    }
    
    //--------------------------------------------------------------------------------------------------
    // METHOD NAME: WinMain
    // RETURN TYPE: int 
    // DESCRIPTION: Entry point of each Win32 application
    //--------------------------------------------------------------------------------------------------
    
    int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
    {
    
    	HRESULT hr = 0;
    
    	WNDCLASSEX wc;
    	ZeroMemory( &wc, sizeof( WNDCLASSEX ) );
    
    	static TCHAR szClassName[] = _T("def_w32_app");
    
    	wc.cbSize = sizeof(WNDCLASSEX); 
    
    	wc.style			= CS_HREDRAW | CS_VREDRAW;
    	wc.lpfnWndProc		= ::WindowProc;
    	wc.hInstance		= hInstance;
    	wc.hIcon			= LoadIcon(NULL, IDI_APPLICATION);
    	wc.hCursor			= LoadCursor(NULL, IDC_ARROW);
    	wc.hbrBackground	= (HBRUSH)GetStockObject(COLOR_WINDOW);
    	wc.lpszClassName	= szClassName;
    	wc.hIconSm			= LoadIcon(NULL, IDI_APPLICATION);
    
    	RegisterClassEx( &wc );
    
    	DWORD dwStyle   = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
    	DWORD dwExStyle = NULL;
    
        HWND hWnd = CreateWindowEx( dwExStyle, szClassName, "Test Window", dwStyle, 0, 0, 800, 600, NULL, NULL, hInstance, NULL);
    
    	return 0;
    }
    This is the whole code, I changed nothing. Funny ain't it? And hWnd is still always NULL and checking for the error returns a "The system cannot find the file specified".

    I'm getting desperate, please help!
    - Matthias

    "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off." - Bjarne Stroustrup

  8. #8
    Join Date
    Mar 2003
    Location
    Germany, K-Town
    Posts
    578
    Hah, I've found the error! I can't say I really understand it, but...

    I had to fill something into the message handler WindowProc(). I first only returned 0 because I didn't even manage to create the window so I didn't really care about handling messages... However, the application seems to verify the message handler in some way (at least I believe that) before creating the window using the WNDCLASS I passed the message handler to.

    Instead of just returning 0, I now wrote some basic code in its body:

    Code:
    LRESULT CALLBACK WindowProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
    {
    	switch (nMsg) 
    	{
    	case WM_COMMAND:
    		break;
    
    	case WM_PAINT:
    		break;
    
    	case WM_DESTROY:
    		PostQuitMessage(0);
    		break;
    
    	default:
    		break;
    		
    	}
    	return DefWindowProc(hWnd, nMsg, wParam, lParam);
    }
    Hard to believe... But it works =)

    If someone here has an idea why the heck I have to write a function which isn't even called before my window even EXISTS, I would appreciate any explanation...

    I don't know why this produced a "file not found" error either and I'm 100% sure that VS6 didn't have this problem. Perhaps it's a bug in the compiler? I don't know.
    - Matthias

    "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off." - Bjarne Stroustrup

  9. #9
    Join Date
    Jun 2003
    Posts
    58
    I think you found ur problem, when used WindowProc, except for dialog box. I think u need to add
    DefWindowProc(...) function; in default area;

    example :

    LRESULT CALLBACK WndProc(HWND ...)
    {
    switch(msg)
    {
    case ... :
    default : return DefWindowProc(hWnd,...);
    }
    }

  10. #10
    Join Date
    Apr 1999
    Posts
    27,449
    Originally posted by matthias_k
    Hah, I've found the error! I can't say I really understand it, but...
    Without DefWindowProc() you are sending messages
    that need to be handled by Windows to never-never land.
    Windows is expecting you to use the message, and then send it
    to Windows, but you failed to do so. Remember, every message
    is sent to your Window procedure, including ones you would
    never expect to receive, but must handle correctly.

    Undoubtedly, one of these messages could have been something
    to do with file handling, who knows. But whatever it was, you
    screwed up the smooth processing of the message by not
    completing the DefWindowProc step. I'm surprised your program
    didn't show other erratic behavior by leaving out DefWindowProc.

    Regards,

    Paul McKenzie

  11. #11
    Join Date
    Apr 2003
    Posts
    1,755

    Smile

    Originally posted by matthias_k
    I don't really know what you mean with "when I got a valid HWND", because I never get a valid HWND
    What I mean is, In my case, I get a valid handle in calling CreateWindowEx. But even I got a valid handle I tried to call GetLastError and if I do that I got the error 2 that you're saying. I found out that this error is generated internally by RegisterClassEx so I asked you if you have any code between the CreateWindowEx and the if statement that might change the HWND and I'm sorry that I did not assumed you step into it.
    Originally posted by matthias_k
    Hard to believe... But it works =)

    If someone here has an idea why the heck I have to write a function which isn't even called before my window even EXISTS, I would appreciate any explanation...

    I don't know why this produced a "file not found" error either and I'm 100% sure that VS6 didn't have this problem. Perhaps it's a bug in the compiler? I don't know.
    When we call CreateWindowEx, it will create the window. Before returning, it will send 3 messages to our WindowProc specifically WM_NCCREATE, WM_NCCALCSIZE, and WM_CREATE in that order. With WM_NCCALCSIZE and WM_CREATE, it's fine when you return 0 to the system. But in case of WM_NCCREATE, we must return TRUE so that the HWND will be valid. In your case, however, you returned FALSE that make CreateWindowEx to return 0.

    Summing up everything, the GetLastError of 2 was generated by RegisterClassEx internally in registering the window class. CreateWindowEx succeeded in creating your window, so the system error of 2 is not touched, and it's ready to return a valid handle. CreateWindowEx sent you WM_NCCREATE, expecting you to return TRUE but you returned 0, and because of that it set its return value to NULL. You recieved NULL and because of that, you called GetLastError, because CreateWindowEx did not touch the error value, you still get the value set by RegisterClassEx. That's the whole story, AFAIK.

    As Paul said, you must let the default window procedure process those messages you don't handle.

    Hope it will clarify your concerns

  12. #12
    Join Date
    Apr 1999
    Posts
    27,449
    Kind of unrelated, but I believe that other graphical, event-driven
    operating systems do not work the same as Windows in terms of
    message handling. You have to tell the OS what messages you
    want to handle, as opposed to Windows sending you everything
    but the kitchen sink. I believe X-Windows works this way (but I
    may be wrong).

    This is sort of like how MFC does things -- you have to explicitly
    state what messages you want by defining them in your
    message map.

    Regards,

    Paul McKenzie

  13. #13
    Join Date
    Mar 2003
    Location
    Germany, K-Town
    Posts
    578
    Ahh, thanks for the explanation.

    That given, I thought it might be the best way to implement the WndProc like this:

    Code:
    LRESULT CALLBACK WndProc( ... )
    {
        switch(message)
        {
         case WM_WHATEVER:
                 // handle the message or not...
                 break;
         }
         return DefWindowProc(...);
    }
    With this code, empty case blocks would not lead to an error, right? Because I always break to the end and return the default procedure. I have seen this approach in a sample code.

    I'm currently only returning the default procedure when entering the 'default' case in the switch statement, otherwise I always return 0L. As far as I know, returning 0 tells the program that I handled a message successfully, therefor I'm a bit confused that rxbagain said CreateWindowEx failed because I always returned FALSE (0) in my Window Proc.

    Can you clarify this?
    - Matthias

    "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off." - Bjarne Stroustrup

  14. #14
    Join Date
    Apr 2003
    Posts
    1,755

    Smile

    Originally posted by matthias_k
    As far as I know, returning 0 tells the program that I handled a message successfully, therefor I'm a bit confused that rxbagain said CreateWindowEx failed because I always returned FALSE (0) in my Window Proc.

    Can you clarify this?
    Most messages we handle are generally handled this way (returning 0 means that there is no error). But for some messages, returning 0 means are error had occured. This is true in WM_NCCREATE message, which is the first message we encounter in our WindowProc when we create window. If we look at the documentation of WM_NCCREATE in MSDN, it says like this
    If an application processes this message, it should return TRUE to continue creation of the window. If the application returns FALSE, the CreateWindow or CreateWindowEx function will return a NULL handle.
    Usually, it's best to consult the documentation whenever we handle a specific message as to how it is handled and what we should return for it.

    Hope it will clarify your concerns
    Last edited by rxbagain; July 28th, 2003 at 03:41 AM.

  15. #15
    Join Date
    Mar 2003
    Location
    Germany, K-Town
    Posts
    578
    It does, thanks.
    - Matthias

    "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off." - Bjarne Stroustrup

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured