• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 242
  • Last Modified:

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.
0
GroundFloor
Asked:
GroundFloor
  • 5
  • 3
  • 2
2 Solutions
 
_Katka_Commented:
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
0
 
GroundFloorAuthor Commented:
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);
0
 
_Katka_Commented:
First: if that piece of code on WM_DESTROY is really called then:
DestroyWindow(hWindow) has to be before PostQuitMessage(0)
otherwise I found nothing disturbing in the entire code..only just
check if hWindow and hInstance are valid numbers..then everything
should be fine..

regards,
Kate
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
Slick812Commented:
hello GroundFloor, I am not certain that I understand your coding methods, I looked at the code for your link at the SwissDelphiCenter, and it appears to be some code that IS NOT CORRECT for simple API APPLICATION code.. . . The code in the link has no explanation of what the code is doing or why. . . If you are interested in API program code with Delphi you might look at this web site -

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

as to your add button code, you might try
program Project1;

uses
  windows, messages;


// Main Window Procedure

function MainWndProc(hWnd,Msg,wParam,  lParam: Integer):Interger; stdcall;
var
  ps: TPaintStruct;
begin
  Result := 0;
  case Msg of
    WM_PAINT:
      begin
        BeginPaint(hWindow, ps);
        SetBkMode(ps.hdc, TRANSPARENT);
        TextOut(ps.hdc, 10, 10, 'Hello, World!', 13);
        EndPaint(hWindow, ps);
      end;
    WM_DESTROY: PostQuitMessage(0);
  end;
 Result := DefWindowProc(hWindow, Msg, wParam, lParam);
end;

// Main Procedure

var
  wClass: TWndClass;
  hWindow, hButton1: HWND;
  Msg: TMsg;
begin

with wClass do
  begin
  {all of the wClass parameters are used here and
  set to 0 if not used}
  hInstance := SysInit.hInstance;
    style :=        CS_DBLCLKS;
    hIcon :=        LoadIcon(hInstance,'MAINICON');
    lpfnWndProc :=  @MainWndProc;
    hbrBackground:= COLOR_BTNFACE+1;
{COLOR_BTNFACE is not a brush, but sets it to a system brush of that Color}
    lpszClassName:= 'Second Class';
    hCursor :=      LoadCursor(0,IDC_ARROW);
   
    lpszMenuName :=  nil;
    cbClsExtra := 0;
    cbWndExtra := 0;
  end;
  RegisterClass(wClass);
  hWindow := CreateWindow(wClass.lpszClassName,
    'API',
    WS_VISIBLE or WS_OVERLAPPEDWINDOW,
    0, 0,
    400, 300,
    0,
    0,
    hInstance,
    nil);

hButton1 := CreateWindow('Button','Ok',
    WS_VISIBLE or WS_CHILD or BS_PUSHBUTTON or BS_TEXT,
   216, 8, 75, 25,hWindow,0,hInstance,nil);

  while GetMessage(Msg, 0, 0, 0) do
  begin
    TranslateMessage(Msg);
    DispatchMessage(Msg);
  end;
end.


 - - - - - - - - - - - - - - - - - - - -

ask questions if you need more information
0
 
GroundFloorAuthor Commented:
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.

0
 
Slick812Commented:
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

0
 
Slick812Commented:
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.
0
 
GroundFloorAuthor Commented:
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?
0
 
Slick812Commented:
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
0
 
Slick812Commented:
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
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

  • 5
  • 3
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now