Link to home
Start Free TrialLog in
Avatar of purplesoup
purplesoupFlag for United Kingdom of Great Britain and Northern Ireland

asked on

Problem closing a window!

I have written a very simple C++ windows application - source code below.

Once the window opens I need to programmatically close (destroy) the window, this time from Visual Basic.

My problem is that DestroyWindow(hWnd) doesn't close the window!

The return code from DestroyWindow is zero, the value of err.LastDllError is 5

If I try to reference the window from Spy++ after calling DestroyWindow() it says it is not valid, so something has happened.

How can I force the window to close?

// Q4App2.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "resource.h"
#include <stdio.h>

#define MAX_LOADSTRING 100

// Global Variables:
HINSTANCE hInst;                                                // current instance
TCHAR szTitle[MAX_LOADSTRING];                                                // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];                                                // The title bar text

// Foward declarations of functions included in this code module:
ATOM                        MyRegisterClass(HINSTANCE hInstance);
BOOL                        InitInstance(HINSTANCE, int);
LRESULT CALLBACK      WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK      About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
       // TODO: Place code here.
      MSG msg;
      HACCEL hAccelTable;

      // Initialize global strings
      LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
      LoadString(hInstance, IDC_Q4APP2, szWindowClass, MAX_LOADSTRING);
      MyRegisterClass(hInstance);

      // Perform application initialization:
      if (!InitInstance (hInstance, nCmdShow))
      {
            return FALSE;
      }

      hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_Q4APP2);

      // Main message loop:
      while (GetMessage(&msg, NULL, 0, 0))
      {
            if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
            {
                  TranslateMessage(&msg);
                  DispatchMessage(&msg);
            }
      }

      return msg.wParam;
}



//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage is only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
      WNDCLASSEX wcex;

      wcex.cbSize = sizeof(WNDCLASSEX);

      wcex.style                  = CS_HREDRAW | CS_VREDRAW;
      wcex.lpfnWndProc      = (WNDPROC)WndProc;
      wcex.cbClsExtra            = 0;
      wcex.cbWndExtra            = 0;
      wcex.hInstance            = hInstance;
      wcex.hIcon                  = LoadIcon(hInstance, (LPCTSTR)IDI_Q4APP2);
      wcex.hCursor            = LoadCursor(NULL, IDC_ARROW);
      wcex.hbrBackground      = (HBRUSH)(COLOR_WINDOW+1);
      wcex.lpszMenuName      = (LPCSTR)IDC_Q4APP2;
      wcex.lpszClassName      = szWindowClass;
      wcex.hIconSm            = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);

      return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HANDLE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // Store instance handle in our global variable

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }


  ShowWindow(hWnd, nCmdShow);
  UpdateWindow(hWnd);

  return TRUE;
}

//
//  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND      - process the application menu
//  WM_PAINT      - Paint the main window
//  WM_DESTROY      - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
      int wmId, wmEvent;
      PAINTSTRUCT ps;
      HDC hdc;
      TCHAR szHello[MAX_LOADSTRING];
      LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);

      switch (message)
      {
            case WM_COMMAND:
                  wmId    = LOWORD(wParam);
                  wmEvent = HIWORD(wParam);
                  // Parse the menu selections:
                  switch (wmId)
                  {
                        case IDM_ABOUT:
                           DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
                           break;
                        case IDM_EXIT:
                           DestroyWindow(hWnd);
                           break;
                        default:
                           return DefWindowProc(hWnd, message, wParam, lParam);
                  }
                  break;
            case WM_PAINT:
                  hdc = BeginPaint(hWnd, &ps);
                  // TODO: Add any drawing code here...
                  RECT rt;
                  GetClientRect(hWnd, &rt);
                  DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);
                  EndPaint(hWnd, &ps);
                  break;
            case WM_DESTROY:
                  PostQuitMessage(0);
                  break;
            default:
                  return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}

// Mesage handler for about box.
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
      switch (message)
      {
            case WM_INITDIALOG:
                        return TRUE;

            case WM_COMMAND:
                  if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
                  {
                        EndDialog(hDlg, LOWORD(wParam));
                        return TRUE;
                  }
                  break;
      }
    return FALSE;
}


Avatar of Axter
Axter
Flag of United States of America image

Hi purplesoup,

Why don't you call PostQuitMessage(0) instead of DestroyWindow?

David Maisonave (Axter)
Cheers!
>>The return code from DestroyWindow is zero, the value of err.LastDllError is 5

That is

//
// MessageId: ERROR_ACCESS_DENIED
//
// MessageText:
//
//  Access is denied.
//
#define ERROR_ACCESS_DENIED              5L

Which window are you trying to close? If you don't have the credentioals to do that, even alternatives will fail.
Avatar of purplesoup

ASKER

Right - I have access denied. So why?

From my vb app I run

call Shell(filename,vbMinimizedFocus)
...
(later)
r = DestroyWindow(hWnd)

So the application is launched from my vb app - what would prevent me from being able to close the window?
Just found something useful - http://www.sowbug.org/mt/archives/000046.html says

"A thread cannot use DestroyWindow to destroy a window created by a different thread"

so I need to find an alternative.
ASKER CERTIFIED SOLUTION
Avatar of jkr
jkr
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Call SendMessage(hDummyOmnisHandle, WM_CLOSE, 0, 0) does it