?
Solved

Problem with CreateWindowEx

Posted on 2006-05-31
4
Medium Priority
?
1,277 Views
Last Modified: 2009-12-16
Hi!

I'm developing a function for a Windows Mobile 5 device, which should display a window and draw some stuff in it. The function is in a DLL which is called repeatedly during the execution of the program. The first, second and third time the function runs, everything works as it should, but from the fourth time and on, no window is displayed.

Calling GetLastError after CreateWindowEx, says the error ERROR_ACCESS_DENIED occured. The message loop aborts immediatelly, and no WM_PAINT event occurs.

Can anyone see what may be causing this?

Thanks!


#include <stdafx.h>

#include <windows.h>
#include <commctrl.h>

static LPCWSTR g_szClassName = _T("Name");

static LRESULT CALLBACK WndProc (HWND hwnd , UINT msg,WPARAM wParam , LPARAM lParam);

static BOOL bsRunning = FALSE;
static UINT nTimerEvent = NULL;

BOOL doCmd(PTCHAR* cmdArgs, DWORD countArgs, PTCHAR* cmdReply, HINSTANCE hInstance)
{
      iAngle = _wtoi(cmdArgs[0]);
      iSpacing = _wtoi(cmdArgs[1]);

      if(!bsRunning)
      {
            bsRunning = TRUE;
            
            WNDCLASS wc;

            wc.style  = 0;
            wc.lpfnWndProc = WndProc;
            wc.cbClsExtra  = 0;
            wc.cbWndExtra  = 0;

            wc.hInstance   = hInstance;
            wc.hIcon       = LoadIcon(NULL,NULL);
            wc.hCursor     = LoadCursor(NULL,IDC_ARROW);

            wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
            wc.lpszMenuName  = NULL;
            wc.lpszClassName = g_szClassName;

            if(!RegisterClass(&wc))
            {
                  *cmdReply = _T("Failed to create window");
                  return FALSE;
            }

            HWND hwnd;
            hwnd = CreateWindowEx(WS_EX_DLGMODALFRAME, g_szClassName, g_szClassName, WS_DLGFRAME | WS_VISIBLE, 0, 0, 240, 320, NULL, NULL, hInstance, NULL);

            if(hwnd == NULL)
             {
                     *cmdReply = _T("Failed to create window");
                     return FALSE;
             }

            nTimerEvent = SetTimer(hwnd,1000,2000,NULL);
            
            MSG Msg;

            while(GetMessage(&Msg,hwnd,0,0))
            {
                                   TranslateMessage(&Msg);
                  DispatchMessage (&Msg);
            }

            UnregisterClass(g_szClassName, hInstance);

            *cmdReply = _T("OK\0");
            return TRUE;
      }
      return FALSE;
}

static void DrawTest(HWND hwnd)
{
      PAINTSTRUCT paintStruct;
      HDC hDC;
      hDC = BeginPaint(hwnd,&paintStruct);

// Drawing here...
      
      EndPaint(hwnd, &paintStruct);
}

LRESULT CALLBACK WndProc (HWND hwnd , UINT msg,WPARAM wParam , LPARAM lParam)
{
      DWORD dwState;

      switch(msg)
      {      
            case WM_CLOSE:
                  DestroyWindow  (hwnd);
                  break;
            case WM_PAINT:
                  DrawTest(hwnd);
                  break;
            case WM_DESTROY:
                  PostQuitMessage(0);
                  break;
            case WM_TIMER:
                  KillTimer(hwnd,nTimerEvent);
                  DestroyWindow(hwnd);
                  break;
            default:
                  return DefWindowProc(hwnd,msg,wParam,lParam);
        }
        return 0;
}

0
Comment
Question by:10goto20
2 Comments
 
LVL 48

Accepted Solution

by:
AlexFM earned 1000 total points
ID: 16798901
One of possible reasons of CreateWindowEx failure is "the system class was registered by a different module". Try to make unique class name for every call to test this.

I don't understand exactly what happens in message loop. Does caller have it's own message loop? What is caller application type?
Can you replace all this stuff with simple DialogBox call? Dialog allows to draw on it's client area exactly as any other window, and code will be much simpler: DialogBox has it's own message loop.
0
 
LVL 3

Assisted Solution

by:srinims
srinims earned 1000 total points
ID: 16806447
put
wc.style = CS_GLOBALCLASS;
and register the class and try;

the reason behind this is


CreateWindow function and the RegisterClass function is the HINSTANCE (either passed as a parameter or as part of the WNDCLASS structure).

The window class name is not sufficient to identify the class uniquely. Each process has its own window class list, and each entry in the window class list consists of an instance handle and a class name. For example, here's what the window class list might look like if a program has two DLLs, both of which register a class name "MyClass", passing the DLL's handle as the HINSTANCE.

 HINSTANCE Class name
 A.DLL MyClass
 B.DLL MyClass

When it comes time to create a window, each module then passes its own HINSTANCE when creating the window, and the window manager uses the combination of the instance handle and the class name to look up the class.

CreateWindow("MyClass", ..., hinstA, ...); // creates class 6
CreateWindow("MyClass", ..., hinstB, ...); // creates class 7
CreateWindow("MyClass", ..., hinstC, ...); // fails

This is why it is okay if multiple DLLs all register a class called "MyClass"; the instance handle is used to tell them apart.

There is an exception to the above rule, however. If you pass the CS_GLOBALCLASS flag when registering the class, then the window manager will ignore the instance handle when looking for your class. All of the USER32 classes are registered as global. Consequently, all of the following calls create the USER32 edit control:

CreateWindow("edit", ..., hinstA, ...);
CreateWindow("edit", ..., hinstB, ...);
CreateWindow("edit", ..., hinstC, ...);

If you are registering a class for other modules to use in dialog boxes, you need to register as CS_GLOBALCLASS, because as we saw earlier the internal CreateWindow call performed during dialog box creation to create the controls passes the dialog's HINSTANCE as the HINSTANCE parameter. Since the dialog instance handle is typically the DLL that is creating the dialog (since that same HINSTANCE is used to look up the template), failing to register with the CS_GLOBALCLASS flag means that the window class lookup will not find the class since it's registered under the instance handle of the DLL that provided the class, not the one that is using it.
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Preface I don't like visual development tools that are supposed to write a program for me. Even if it is Xcode and I can use Interface Builder. Yes, it is a perfect tool and has helped me a lot, mainly, in the beginning, when my programs were small…
Summary: This tutorial covers some basics of pointer, pointer arithmetic and function pointer. What is a pointer: A pointer is a variable which holds an address. This address might be address of another variable/address of devices/address of fu…
The goal of this video is to provide viewers with basic examples to understand recursion in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use while-loops in the C programming language.

850 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question