Link to home
Start Free TrialLog in
Avatar of GroundFloor
GroundFloor

asked on

How to delete a button?

I am trying to learn more about API programming using code i found at:

http://www.swissdelphicenter.ch/en/showcode.php?id=411

I noticed that it did not destroy the window when the program it creates is closed and i seem to have figured that out myself.

However, i put the code in to add a button to the form - but it is not deleted from memory when the program is closed.

Does anyone know how to delete a button created with CreateWindow?

I tried DestroyWindow() but it didn't work and i've looked on the internet but cannot find anything.
Avatar of _Katka_
_Katka_
Flag of Czechia image

Hi, what's your code for adding the button ?
The problem is probably in specifying a
parental component and your window is
not aware of containing it (the button).

regards,
Kate
Avatar of GroundFloor
GroundFloor

ASKER

Hi Katka

I changed WM_DESTROY: PostQuitMessage(0); to WM_DESTROY: PostQuitMessage(0); DestroyWindow(hWindow)

That destroyed the window on closing.

I added the button with the following code under ShowWindow(hWindow, CmdShow);

  Button1 := CreateWindow('Button', 'OK', WS_VISIBLE or WS_CHILD or BS_PUSHLIKE or BS_TEXT,
                           216, 8, 75, 25, hWindow, 0, hInstance, nil);
SOLUTION
Avatar of _Katka_
_Katka_
Flag of Czechia 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
ASKER CERTIFIED SOLUTION
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
Thanks for your help Katka

Slick812  - thanks for the demo code.  I couldn't get it to work 100% but was able to figure out a few more things from it.

I figured out that each button or other object is a "window" itself and therfore needs to have its "handle" destoyed when exiting the program.  A little bit of extra code fixed it.

I increased the points and will split them between you both for your help.

You do not need to destroy any windows that are child windows or other window like the button is a child window of the hWindow, so when the system destroys the hWindow it will automatically destroy the hButton1 window. . . . You do NOT need the -

DestroyWindow(hWindow);

in your code, your message handing is incorrect, you MUST let the system get the WM_DESTROY message to the

DefWindowProc(hWindow, Msg, wParam, lParam);

and not bypass it like your code does

program ApiProgram;

uses
  Windows, Messages;

{$R *.RES}

var
winClass: TWndClass;
hForm1, hButton1: Integer;
MainMsg: TMSG;

function WindowFunc(hWnd, Msg, wParam, lParam: Integer): Integer; stdcall;
begin
case Msg of
  WM_DESTROY: PostQuitMessage(0);
  {do not block the WM_DESTROY message, you must let the DefWindowProc be called
   with this destroy message for the system to destroy the window and its child windows}
   
  WM_COMMAND: if lParam = hButton1 then PostMessage(hForm1,WM_CLOSE,0,0);
    {when a button is clicked a WM_COMMAND message is sent with the lParam set to the
     button's Handle}
  end;
{there is no special window message handling, so let all messages go to
  DefWindowProc  just to be safe}
Result := DefWindowProc(hWnd,Msg,wParam,lParam);
end;

begin
ZeroMemory(@winClass, SizeOf(winClass));
with winClass do
  begin
  hInstance := SysInit.hInstance;
  hIcon := LoadIcon(hInstance,'MAINICON');
  lpfnWndProc := @WindowFunc;
  hbrBackground := COLOR_BTNFACE+1;
  hCursor := LoadCursor(0,IDC_ARROW);
  lpszClassName := 'A Class Name';
  end;

RegisterClass(winClass);

hForm1 := CreateWindow(winClass.lpszClassName,
    'Form Caption', // title bar Caption here
    WS_OVERLAPPEDWINDOW or WS_VISIBLE,      // window style
{WS_OVERLAPPEDWINDOW is the default standard main window with a
Title bar and system menu and sizing border, there is No WS_CHILD here}
    100,      // horizontal position of window
    50,      // vertical position of window
    356,      // window width
    220,      // window height
    0,      // handle to parent or owner window
{this is the MAIN window, so it does not have a parent}
    0,      // handle to menu or child-window identifier
    hInstance,      // program instance handle
    nil       // pointer to window-creation data
   );

CreateWindow('STATIC','A Title Label',
 WS_VISIBLE or WS_CHILD or SS_CENTER,3,10,347,16,hForm1,0,hInstance,nil);

hButton1 := CreateWindow('BUTTON', 'Close Me',
    WS_VISIBLE or WS_CHILD or BS_PUSHBUTTON,
    140,146,64,28,hForm1,0,hInstance,nil);

SendMessage(hButton1,WM_SETFONT,GetStockObject(ANSI_VAR_FONT),0);

while GetMessage(MainMsg,0,0,0) do
  begin
  TranslateMessage(MainMsg);
  DispatchMessage(MainMsg);
  end;
// you do not need to call Halt or anything else here
// program will terminate when it gets to the  END.  code next
END.
Thanks Slick812 - but i tried out yourprogram above when compiled through MemProof to check if everything was deleted as expected.  

It pointed out that the button and label was not destroyed and give the message that if CreateWindow or CreateWindowEx is used that the window handle must be destroyed by DestroyWindow or by passing a WM_DESTROY message to the default window procedure.

It also pointed ot that DestroyIcon needed to be used too.

odd?
the  MemProof is correct in one way, that you created windows and did not specifically call a function to Destroy them, this is waht it is suppose to do, However!  the system will destroy the window in it's WM_DESTROY message sent to the  DefWindowProc  - - - it seems like you could figure this just from the message name  "WM_DESTROY"  Also, the system realizes that the child windows of a Destroyed window will be without a parent, so it will automatically perform all nessary system actions needed to destroy ALL of a destroyed window's Child windows. . .
and I do not understand the  reference to -
DestroyIcon

I use the LoadIcon( ) function which does NOT require a DestroyIcon. . .

you really should read the Win32 Help for all of the API Functions, Messages and Methods you use in your code,  the Help has some useful information about what you need to do or use many times. . .

I have already given you a web address for a web site that you should go to and read up on using API to make windowed projects -

http://www.angelfire.com/hi5/delphizeus/index.html

and the page that explaines window creation and handles and messages is at -

http://www.angelfire.com/hi5/delphizeus/first1.html

it is worth your time to read that page if you are going to do anymore API programming
if you want current information about the API methods, you might go to the MSDN developers library at -

http://msdn.microsoft.com/library/default.asp

and do word searches for specific functions, messages, things (like - windows, buttons, messages, edits).

you may want to read all of the pages that are availiable at the MSDN Library for the subject of "Windows", ,  starts at page -

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/windows.asp