WinAPI

WinAPI

Capture the minimize button, before application will be minimized
Call GetProcAddress procedure
Checking whether a form is still around
How to determine an existing instance of a program is already running
Intercept WM_KEYDOWN event
Popup menu by clicking left mouse button
Access icons in .exe-file
Own message handler
Keyboard routines
EnumChildWindows Example
Getting window handles from instance handle
Get line from TMemo
Previous Instance
EnumChildWindows - ExampleCode
Difference between Smart Callbacks and Dumb Callbacks
Is menu open
FindWindow
Minimize a non-delphi window from a delphi program
WinAPI functions
TMessage vs TMsg
Button does not respond to enter key
Simulating Key presses
Key presses / edit position
Avoiding close
Speaker Bleep
How to call a function with a TFarProc
Callback functions
Terminate vs. PostMessage(Handle, wm_Close, 0, 0)
How to detect program is already running
TPolygon Object OnClick algorithm question
Problems with GetSystemMetrics(SM_CYMENU)
Stuffing Keystrokes into buffer
Insert / overwrite
How can I trap a system error message
Find window problem
How do I disable mouse cursor
Mouse cursor position
Shift Tab don't activate onexit event
Task ID
Setting the active window
Updating Cursor immediately
Change System Menu
Move Mouse through Code
WinExec
How to drop down a combo box list
Capturing the Maximize message
Scroll Listbox programmatically
Moving the cursor only in the x-axis
Send Messages to a control
Previous Instance, FindWindow
Waiting for an exec'd application to complete
_hread
Manually drop-down a combobox
Imitating Key Strokes
Mouse control within and area of the screen
Need WinProc
Number of colors used in Windows
EnumWindows()
Undo in a memo field
Terminate all running applications
How to keep apps iconized
Trapping WM_ENDSESSION message
Restarting Windows
Automate memo or window scrolling
Virtual key values
Getting DOS and Windows version numbers
Flashing an applications's title bar and/or icon
Determining number of lines a memo can show
Exiting Windows from within a Delphi app
Simulate sending key to own application
ExitWindows
System Menu
GetModuleFileName
CM_MOUSELEAVE


Capture the minimize button, before application will be minimized

Question


Does anybody know how to capture the minimize button press and act on

it before it actually minimizes the form?



Answer


A:

You should intercept WM_SYSCOMMAND messages like this:

unit Unit1;



interface



uses

  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,

  Forms, Dialogs;



type

  TForm1 = class(TForm)

    public

    procedure WMSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;

  end;



var

  Form1: TForm1;



implementation



{$R *.DFM}

procedure TForm1.WMSysCommand;

begin

  if (Msg.CmdType = SC_MINIMIZE) or

     (Msg.CmdType = SC_MAXIMIZE) then

    MessageBeep(0);

  DefaultHandler(Msg);

end;



end.




Call GetProcAddress procedure

Question


I have to call GetProcAddress procedure, but I don't know how.



Answer


A:

First you need to declare a procedural data type. Here is a quick example

that should explain it. BTW you will need a procedural data type for all of

the different command lines you will be calling.



type

  TMyProcType = function( X, Y: Integer ): Integer;



  ...

  ...



var

 nHandle: THandle;

 MyProcType: TMyProcType

begin

  nHandle := LoadLibrary( 'MYDLL.DLL' );



  if nHandle < 32 then

    raise EDLLLoadError.Create( 'Cant load the sucker' );



  @MyProcType := GetProcAddress( nHandle, 'MYFUNCNAME' );



  { Now call it like a function, ex:}

  z := MyProcType( 10, 10 );



  FreeLibrary( nHandle );




Checking whether a form is still around

Question


Checking whether a form is still around?



Answer


A:

Look in the API help under EnumChildWindows

It's prototype is:

(WndParent: HWnd; EnumFunc: TFarProc; lParam: LongInt): Boolean;



Use the application handle for WndParent.

EnumFunc which is written by you checks for the existence of the window -

remember to export it.



Also try the API function:



Function IsWindow(Wnd: HWnd): Boolean;



The IsWindow function determines whether the given window handle is valid. 




How to determine an existing instance of a program is already running

Question


How can a Delphi program check if an existing instance of it is already

running?

Answer


A:

If hPrevInstance<>0 then Terminate;



As one of the first lines of the project source will terminate the instance of

the application just run if another is already running.



A:

Try this in the project source file:



{usual stuff at the top of the project source file

var hwnd: Word;



begin

  if hPrevInst = 0 then

  begin

    Application.CreateForm(TForm1, Form1);

    Application.Run;

  end

  else

  begin

    hwnd := FindWindow('TForm1', nil);

    if (not IsWindowVisible(hwnd)) then

    begin

      ShowWindow(hwnd, sw_ShowNormal);

      PostMessage(hwnd, wm_User, 0, 0);

    end;

    else

      SetWindowPos(hwnd, HWND_TOP, 0,0,0,0,

        SWP_NOSIZE or SWP_NOMOVE);

  end;

end.



In the form's PAS file add a message response function for the wm_User

message.



{in the form declaration}

public

  procedure WMUser(var msg: TMessage); message wm_User;



{in the implementation section}

procedure TForm1.WMUser(var msg: TMessage);

begin

  Application.Restore;

end;



A:

     if hprevinst <> 0 then begin

          bringwindowtotop(findwindow('TForm1', nil));

          halt;

          end;



    Application.CreateForm(TForm1, Form1);

    Application.Run;




Intercept WM_KEYDOWN event

Question


I'm just writting a new component base od TCustomControl and I have

problems with intercepting KeyDown event.

I want to intercept VK_DOWN. The overriden KeyDown method is not

called when I press down arrow key (for other keys it's OK). The

same with intercepting WM_KEYDOWN method:

   procedure WMKeyDown(var Message : TMessage); message WM_KEYDOWN;

Answer


A:

The VK_DOWN, VK_UP, and the VK_TAB can't be accessed by using KeyDown.  Use

the 'OnMessage' event to handle those keys. The 'OnMessage' event gives you

the full message along with all it's parameters.



A:

What you need to do is override the KeyDown method of TCustomControl ie.

in the protected section of you new object type, insert this line:



    procedure KeyDown(var Key: Word; Shift: TShiftState); override;



then in your object's implementation you do something like:



procedure TMyObject.KeyDown(var Key: Word; Shift: TShiftState);

begin

  inherited KeyDown(Key, Shift);

  if (Key in [VK_UP, VK_DOWN, VK_NEXT, VK_PRIOR, VK_HOME, VK_END]) then

    {do key movement work}

end;



A:

1. To write OnMessage hander for the Application

2. To intercept WM_GETDLGCODE message first and return DGLC_WANTARROWS.



The probles was that messages WM_KEYDOWN: VK_UP, VK_DOWN, VK_TAB are

not sent to the control as long as the control does not response

to WM_GETDLGCODE message.


Popup menu by clicking left mouse button

Question


I would like the popup menu to appear when the user clicks with the left

button.

Answer


A:

In your circumstances it might be a good idea to swap the left and

mouse right buttons.  Use the following API call to do this



    Function SwapMouseButton(Swap : Boolean) : Boolean;



    Parameters - Swap : Non0Zero to swap buttons or zero to to restore



    Returns a non-zero if meanings reversed; zero if not;



I would like the popup menu to appear when the user clicks with the left

button.



A:

How about setting the AutoPopup property to false, then on your form's

OnClick event call the Popup's Popup Method. Of course you could

leave AuotoPopup which would allow either button to do the trick.


Access icons in .exe-file

Question


I want to know if it is possible to access the icons that is stored in the

.exe of a file from a delphi form.

Answer


A:

Have a look at the ExtractIcon() API. Do note that the IconIndex

parameter is specified as being of Word type; but to get the

functionality of returning the total number of icons in the specified

file you're supposed to pass -1; you can do this by passing either $FFFF

or Word(-1).


Own message handler

Question


How do I write my own message handler within a base object.

The Main problem relates to unhooking the callbacks, documentation I had

recomended unhooking from outside the callback which mean't passing messsages

from the dll to the application.

Answer


A:

What you can do is create a message handle using RegisterWindowsMessage.

The code should look something like this:



        StopMessage := RegsiterWindowsMessage('WM_STOP');



You should use RegisterWindowsMessage in both the DLL and in your application.

Then you can use StopMessage as the message type in a SendMessage or

PostMessage function call from the DLL.  In your application you can trap

this message

by checking for StopMessage in your WndProc function like this:



procedure TMyForm.WndProc(Message : TMessage);

begin

        if Message.Message = StopMessage then

        begin

                { do processing for StopMessage here }

        end;

end;


Keyboard routines

Question


Does anybody know if it is possible to distinguish between the right shift key

and the left shift key in Delphi?

Answer


A:

{ using this code you can determine which key is being pressed }



type

   tkeyspressed     = (kpRightShft, kpLeftShft, kpCtrl, kpAlt);

   tkeyspset        = set of tkeyspressed;



function getkeyshfstate : tkeyspset;

begin

   result := mem[$40:$17];    { $40 is the famous bimodal segment/selector }

   end;





{ ----------------------------------------- }



Use the code as a set. To know if the left shift is being pressed you do



     ...

     if getkeyshfstate in [kpLeftShft] then

          .....



     .....



A:

Const

     kpRightShft    = 1

     kpLeftShft     = 1 shl 1;

     kpInsertActive = 1 shl 7;

     kpLeftCtrl     = 1 shl 8;

     kpLeftAlt      = 1 shl 9;

     kpSysReq       = 1 shl 10;

     kpNumLockOn    = 1 shl 11;





function getkeyshfstate : word;

begin

   result := memw[$40:$17];    { $40 is the famous bimodal segment/selector }

   end;





This is how you use it now:





     ...

     if getkeyshfstate and kpLeftShft <> 0 then

          .....                                        { Left Shift is pressed }





     ...

     if getkeyshfstate and kpLeftCtrl <> 0 then

          .....                                        { Left Ctrl is pressed }


EnumChildWindows Example

Question


I've been trying to write a function to make finding child windows easier

using EnumChildWindows. I can't get it to work.

Answer


A:

I suggest that you do as follows. Please make shure that in the compiler

options you select smart callbacks ON. Or use the compiler directive as I

included it here.







{$K+}          { smart callbacks on}

unit WndX;



interface

uses

  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,

  Forms, Dialogs;



function FWC(P: integer; C: String; I: integer): integer;

function EnumChildProc(HWnd: integer; lParam: longint): Boolean;

function Left(inString : String; numChars : Byte) : String;



implementation



var

   Counter  : integer;

   Cnt      : Integer;

   FWCWnd   : integer;

   CMatch   : array[0..254] of char;





function EnumChildProc(HWnd: Integer; lParam: longint): Boolean; export;   {

must be declared export }

var 

   ClsName  : array[0..31] of char;

   ClsLen   : Integer;

begin

   GetClassName(HWnd, ClsName, 31);

   If strcomp(ClsName, CMatch) = 0 then 

      Counter := Counter + 1;

   Result := Counter <> cnt;

   if not result then

      FWCWnd := HWnd;

   end;





function FWC(P: integer; C: string; I: integer): integer;

begin

   FWCWnd := 0;

   strpcopy(CMatch, C);       { convert from string to ASCIIZ }

   Cnt := I;

   EnumChildWindows(P, @EnumChildProc, 0); { no need for makeprocinstance! }

   FWC := FWCWnd;

   end;



end.


Getting window handles from instance handle

Question


I am trying to write a simple launcher app that launches a list of apps

when started, minimizes them all when minimized, and closes them all when

closed.

None of the messages for closing or minimizing will work off an instance

handle, which I get from WinExec.

Answer


A:

It's work, but you can do it in two steps. First you have to obtain the task

from the instance. To do so you can use toolhelp to walk the task list looking

for a task that has your instance.



Step two. A new walk. Once you have the task you call EnumTaskWindows to

walk the windows list until you find the one. It may be the first one.



In the second case you have to pass a pointer to your own walk function.



I hope this helps. But you will have to read in the WINAPI help section

looking for the data in the structures.


Get line from TMemo

Question


How do I know which line the cursor is on in a TMemo?

Answer


A:

You can use the Windows API messages EM_LINEFROMCHAR and

EM_LINEINDEX to determine the current line and offset within that

line (starting from SelStart).



   var

     LineNum: longint;

     CharsBeforeLine: longint;

   begin

     LineNum := SendMessage(Memo1.Handle, EM_LINEFROMCHAR, Memo1.SelStart,0);

     CharsBeforeLine := SendMessage(Memo1.Handle, EM_LINEINDEX, LineNum, 0);

     Label1.Caption := 'Line ' + IntToStr(LineNum +1)

     Lebel2.Caption := 'Position ' + IntToStr((Memo1.SelStart -

CharsBeforeLine) + 1);

   end;


Previous Instance

Question


I have a program that is minimized. When I execute it again, it does not

run again, but, the first copy remains minimized.

Answer


A:

In your main form:

procedure TForm1.AppOnActivate(Sender: TObject);

begin



 Self.WindowState := wsNormal;

 {Self.Minimize1.Caption := 'Mi&nimize';

 }

 end;

procedure TForm1.FormActivate(Sender: TObject);

begin

    Application.OnActivate := AppOnActivate;



end;



In Your main unit:

begin

  { If there's another instance already running, activate that one and

    terminate this one }

  if HPrevInst <> 0 then begin

    LoadPreviousInstance;

    Exit;

  End;

  Application.CreateForm(TForm1, Form1);

  Application.Run;

end.



Then here is where the work is done - I know it is alot of code but 

it will do the trick (the problem is that you have to activate the 

application and then restore the form)



unit PrevInst;



interface



uses WinProcs, WinTypes, SysUtils;



type

  PHWnd = ^HWnd;



{EnumFunc must be  exported. It  is used as the callback function for

the API call to EnumWindows}



function EnumFunc(Wnd : HWnd; TargetWindow : PHWnd): Bool; export;

procedure LoadPreviousInstance;



implementation



function EnumFunc(Wnd : HWnd; TargetWindow : PHWnd): Bool;

{Callback function for EnumWindows. EnumWindows passes the handle 

(Wnd) of each open parent window (not children). }

var

  ClassName : array [0..30] of char;

begin

  Result := True;

  if GetWindowWord(Wnd,GWW_HINSTANCE) = HPrevInst then begin

    GetClassName(Wnd,ClassName,30);

    if StrIComp(ClassName,'TApplication') = 0 then begin



      {It is the window we want - assign it to TargetWindow}



      TargetWindow^ := Wnd;

      Result := False;     {Stop enumeration - see EnumWindowsProc

                            in the API help}

    end;

  end;

end;



procedure LoadPreviousInstance;

var

  PrevInstWnd : HWnd;

begin

  PrevInstWnd := 0;

  {Pass each open parent window's handle in turn to EnumFunc}

  EnumWindows(@EnumFunc,Longint(@PrevInstWnd));

  if PrevInstWnd <> 0 then        {We have a handle to the previous

                                   instance}

      BringWindowToTop(PrevInstWnd); End;



end.


EnumChildWindows - ExampleCode

Question


EnumChildWindows - ExampleCode?

Answer


A:

I suggest you start with a hWnd of 0, meaning the screen. You can recurse from

there.



{$K+,F+}     { IMPORTANT use smartcallbacks }



function EnumChilProc(hwnd: thandle; lparam: longint) : wordbool; export;

{ IMPORTANT use export }

begin

{ you are called here with hwnd = the child window

     do what you want, store it in a tlist or array or whatever

     lparam is an arbitrary parameter that you pass from EnumChildWindows

     you may cast it to a tlist if you want

}

     result := true;  { return false if you want to abort the enumeration }

     end;



{$F-}



Function myenum(parentwnd : thandle);

begin

     enumchildwindows(parentwnd, @EnumChildProc, 0);   {you may replace the

last 0 with any value that you want to send to lparam in the EnumChildProc}

end;



A:

This example sets the font of all child windows, but you can adapt this a lot of

different ways. I'm pretty sure your callback function cannot be a method in an

object (except possibly by making it a class method). The lParam argument is

user-definable.  Notice that I used MakeLong to make a longint out of two words.

It is not mentioned in the Help, but is part of WinProcs. The following must

be compiled with $K+ (Smart Callbacks), which is global to each UNIT (at least

it was in BPW). If you don't want to use smart callbacks, you must declare a

variable of type TFarProc, and use MakeProcInstance and FreeProcInstance. See

second example. There are certain cases in which Smart callbacks are not

allowed, but EnumChildWindows is NOT one of them.



function SetChildWinFont(aWnd: hWnd; lParam: longint): Bool; export;

begin

  SendMessage(aWnd, wm_SetFont, LoWord(lParam), HiWord(lParam));

  SetChildWinFont := true;

end;



{$K+}



begin

  EnumChildWindows(HWindow, TFarProc(@SetChildWinFont), MakeLong(aFont, 1));

end;



{$K-} or {$K+}



var

  MyProc: TFarProc;



begin

  MyProc := MakeProcInstance(@EnumChildWindows, hInstance);

  EnumChildWindows(HWindow, MyProc, MakeLong(aFont, 1));

  FreeProcInstance(MyProc);

end;


Difference between Smart Callbacks and Dumb Callbacks

Question


A Smart Callback is one in which you do not need to use MakeProcInstance.

MicroSoft docs generally all say that you have to use

MakeProcInstance/FreeProcInstance whenever you use a callback function of any

kind.  A dumb callback (first time I've heard the term used), is the opposite,

i.e. you have to use MakeProcInstance and FreeProcInstance.

Answer


Borland tools are 'smart' and can get around that in many instances through the

use of Smart Callbacks.  That is all you really need to know to use them.  So

far as what's really going on, as I understand it, MakeProcInstance does a type

of thunking.  "What's thunking?", you may ask.  Kind of hard to explain, but

basically it places a layer of code between two modules in which one needs to

call the other, to 'translate' things.  In this case, I think it mostly has to

do with properly setting the DS and SS registers upon entering and leaving the

callback function.


Is menu open

Question


Is there a (preferably non-Delphi specific) way to tell if the menu as a

whole is currently open/selected?

Answer


A:

{....}

type

  TForm1 = class(TForm)

    MainMenu1: TMainMenu;

    item01: TMenuItem;

    item11: TMenuItem;

    Item21: TMenuItem;

  private

    { Private declarations }

  public

	{----- HERE ------}

        PROCEDURE WMMENUSELECT(VAR M: TWMMENUSELECT);MESSAGE WM_MENUSELECT;

  end;



{...}



PROCEDURE Tform1.WMMENUSELECT(VAR M: TWMMENUSELECT);

begin

     inherited;

	{This beeps even if it is the sysmenu (control menu) and/or on any 	

selected item: }

     {   messagebeep(MB_ICONASTERISk);  }

     

     {This beeps when mainmenu1 is opened, but only beeps on item[0]}

          if M.menu=Mainmenu1.handle then

                  messagebeep(MB_ICONASTERISk);



end;



end.


FindWindow

Question


I need to pass 0 Long as one of the parameters in FindWindow.

Answer


A:

In Delphi, 0 can be a byte, integer, word, longint, real, double.  But in this

case FindWindow is wanting a PChar type, which is essentially a pointer to an

array of char.  Nil should work just fine; it works for me.  For the second

parameter, I noticed that you're using double-quotes ["].  That is incorrect

syntax.  In Delphi, strings are denoted by single-quotes ['].  For instance,

try:



function FindaWin: hWnd;

begin

  Result := FindWindow(nil, 'Title');

end;



By the way, a PChar is not compatible with a pascal string, but in the above

example, the compiler accepts the literal 'Title' as a PChar just fine.  If you

wanted to write a function that would accept a pascal string and use it to call

FindWindow, you could do this:



function FindaWin(aName: string): hWnd;

var

  aStr: array[0..255] of char;

begin

  Result := FindWindow(nil, StrPCopy(aStr, aName));

end;


Minimize a non-delphi window from a delphi program

Question


I need to minimize a window from another program (non delphi) when

my program executes. Is there a way to send this window a message

to minimize itself?

Answer


A:

First you need to get the HWND (Window Handle see the WinAPI help) of the

window you want to close (The subject of another thread here.) Then try

this Windows API routine. SendMessage( hWnd, WM_SIZE, SIZE_MINIMIZED, 0);

This sends the message to the window in hWnd, that the user pressed

the minmize box or selected it from the system menu.



A:

A better solution is calling the Windows API function: CloseWindow(hWnd) -- or

ShowWindow(hWnd, SW_MINIMIZE);


WinAPI functions

Question


I'm having trouble figuring out how to use the functions that are listed in the

WinAPI Help file, and would appreciate any help that anyone has to offer ...

The specific function I am looking at is WinExec.

Answer


A:

    To call Windows API functions like WinExec:



1.  You need WinProcs (and often WinTypes) in the uses clause

    of the unit from which you want to make the call.



2.  If you want to supply a string constant as the actual

    parameter where the formal parameter is PChar, you need to

    check Extended syntax in the Options | Project [Compiler]

    dialog (or alternatively use the {$X+} compiler directive at

    the top of the unit concerned.



3.  Then just code something like:

	     WinExec('Notepad', SW_ShowMaximized)


TMessage vs TMsg

Question


Code taht I got from the 'net uses TMessage, and it worked OK. Docs use TMsg,

and do not mention TMessage. What's the deal?

Answer


A:

Use TMessage for cracking messages passed to a window.  TMsg is for certain API

calls such as PeekMessage, TranslateMessage, GetMessage, etc., in other words,

stuff that you probably won't be doing in a Delphi app.  TMsg also includes info

about where the mouse cursor was at the time the message was generated, and a

time stamp.


Button does not respond to enter key

Question


I want to make a Button respond to pressing the Enter/Return key. Note the

following snippet.



buttonKeyPress(.....)

begin

if key = #13 then do SOMETHING;

else do SOMETHING ELSE;

end;



Using this programming, if the return key is pressed NOTHING happens.

The trace-over just skips it.

IF a key OTHER than the return key is pressed, then SOMETHING ELSE does

get done!?

Answer


A:

The reason for this is that TButton or TBitBtn uses the Windows standard button

control, which uses the Return key.  To overcome this, you will need to create a

descendant of TButton and add a message handler for wm_GetDlgCode, like this:



type

  TMyButton = class

  protected

    procedure WMGetDlgCode(var Msg: TWMGetDlgCode); message wm_GetDlgCode;

  end;



procedure TMyButton.WMGetDlgCode;

begin

  inherited;

  Msg.Result := Msg.Result or dlgc_WantReturn;

end;



See the WinAPI help file for further information on this message.


Simulating Key presses

Question


When my users enter a certain text box, I want conditional text to fill in

automatically. Let's use the following fictitious scenario.

In Edit1.Text the user fills in "CT" the state code for CT. Edit2 collects

phone number information. I know that "(203) " should be the first six

characters entered. So, using the OnEnter method of Edit2 I would like the

following to happen; the text value set to "(203) " and the cursor to

position itself at the end of those characters.

I imagine that there is an easy way to reposition a cursor in an edit box

that I do not know. If so, I'd appreciate hearing about it.

I figured I could use the following code (don't ask me why I figured this

would work ... it seems to be some vestigal memory from a something I

read or something.). In any case, it doesn't work.  Any insights?



begin

  Edit2.Text := '(203 )';

  SendMessage(WM_CHAR,VK_END,0,0);

end;

Answer


A:

Try this:



begin

  Edit2.Text := '(203 )';

  Edit2.selStart:=Edit2.GetTextLen;

end;



Also, you might want to set Edit.AutoSelect to False, otherwise when a user tab

to this editBox, the text you inserted is selected, and if the user starts

typing it will be overwrited.


Key presses / edit position

Question


I imagine that there is an easy way to reposition a cursor in an edit box

that I do not know.

Answer


A:

Try this 2 Edit box sample below.



unit Cursor;



interface



uses

  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,

  Forms, Dialogs, StdCtrls;



type

  TForm1 = class(TForm)

    Edit1: TEdit;

    Edit2: TEdit;

    procedure Edit1Change(Sender: TObject);

    procedure Edit1KeyDown(Sender: TObject; var Key: Word;

      Shift: TShiftState);

  private

    { Private declarations }

  public

    { Public declarations }

  CurPos : integer;

  end;



var

  Form1: TForm1;



implementation



{$R *.DFM}



procedure TForm1.Edit1Change(Sender: TObject);

begin

CurPos := Edit1.SelStart;

 edit2.Text := IntToStr(CurPos);

end;



procedure TForm1.Edit1KeyDown(Sender: TObject; var Key: Word;

  Shift: TShiftState);

begin

If Key = VK_LEFT then dec(CurPos);

if Key = VK_RIGHT then inc(CurPos);  {RIGHT Arrow}

edit2.text := inttostr(CurPos);

end;



end.


Avoiding close

Question


I am writing an application that needs to to run continously, so if the user

clicks on the close button it should minimize. I tried to use the on close

event in the main form giving the value caNone and caMinimze to the var

parameter Action. However, the application quits.

Answer


A:

     type



       skAction = ( skfNone, skfClose, skfMinimize, skfMaximize, skfReload

     );





procedure TSKDForm.FormClose(Sender: TObject;

  var Action: TCloseAction);

begin

  case FormAction of

    skfNone :

    begin

      Action := caNone;

      ShowWindow( Handle, SW_MINIMIZE );

      Exit;

    end;

    skfClose :

    begin



{ my clodr window code }

      Exit;

    end;

    skfMinimize :

    begin

      Action := caMinimize;

      Exit;

    end;

  end;

end;


Speaker Bleep

Question


Anybody know how to make the PC speaker bleep in Delphi, like when a user

types a wrong character?

Answer


A:

Try to take a look in the Windows API on-line help and search for

MessageBeep procedure...



Anyway, something like the following may be right for you:



uses WinProcs;



...



MessageBeep( -1 );



...



A:

If you use the WINDOS unit in your uses clause, you can do a standard Pascal

write of the BEL ASCII character to output:



Write(Chr(7))



I think it produces the rather prosaic BIOS type BEEP.


How to call a function with a TFarProc

Question


I gather I can use GetProcAddress to return a pointer to a procedure in a

.drv file. For example, ExtDeviceMode to get or change some printer settings.



Does anyone know how to use the pointer to call the function? I get a

type mismatch however I try.

Answer


A:

In the WinProcs unit, ExtDeviceMode is declared as a 'type' of procedure,

like this:



type

  TExtDeviceMode = function(Wnd: HWnd; Driver: THandle;

    var DevModeOutput: TDevMode; DeciveName, Port: PChar;

    var DevModeInput: TDevMode; Profile: PChar; Mode: Word): Integer;



So, what you want is to declare a variable of that type, which will in

reality be a pointer, load the printer driver, and get the address to the

function, like this:



var

  aModule: THandle;

  ExtDeviceMode: TExtDeviceMode;

begin

  aModule := LoadLibrary('HPPCL.DRV');

  if DeviceModule < 32 then

    raise Exception.Create('Can''t load printer driver');

  try

    @ExtDeviceMode := GetProcAddress(aModule, 'ExtDeviceMode');

    if (@ExtDeviceMode = nil) then

      raise Exception.Create('Can''t find ExtDeviceMode function');

    ExtDeviceMode(   ...  );



  finally

    FreeLibrary(aModule);

  end;

end;


Callback functions

Question


What is a callback function and is it supported by Delphi?

Answer


A:

A Callback function is a windows function that gets called every time

something happens.  You could sorta say that message events are callback

functions, but they're not.  You can do callback functions in delphi but i

wouldn't say it "supports" them. I.e. you have to declare callback

functions(the dec's are in winapi.hlp) the declarations and constants are

not in wintypes or winprocs etc. You also have to put callback functions

into a .dll i believe there a ways getting around that, but in the help it

says to put callback function code into a dll.  Callback functions can do

lots of advanced windows things like hooks,subclassing other apps etc.



To subclass another app use setwindowlong(). You'll see help in winapi.hlp



To install hooks on certain things look up setwindowshookex() the VB

sendkeys function is an example of the wh_journalplayback hook.

Alot of these functions in my eyes are best used to make add on programs for

other programs.  or to tell what's happening in another program.  By

subclassing another program you can find out everything that is sent to it,

and handle its messages etc. An example could be you subclass aol or prodigy

chat and allow alias's and actions and such in the chatroom. (there'd be no

need to subclass mirc as it already supports 'em,just in case anybody didn't

like the example)

You can also do many other powerful things with hook/callback functions such as



Creating a win95 style taskbar for win 3.1

Finding out whats heading thru the comport

Make programs like interactive tutors that came with delphi



I can't really think of anything else offhand, if your trying to figure out

whether you need to or should use a callback function, let us know what

you're trying to do and somebody(probably not me) will know what the best

call is.



A:

Callback functions is procedures/functions that you use to notify (for

instance) something in your code. For example, imagine a procedure that

install a software in your hard disk. In the Install procedure, you may want

to update a gauge in your screen to tell the user how much of the installation

already has passed, right? So, you can pass a procedure in a parameter of the

Install procedure that points to another function that update this gauge. Too

confusing? An example:



Type

    TGaugeUpdateFunc = procedure( pos : integer );





( ... )



procedure Install( GaugeFunc : TGaugeUpdateFunc; drive : byte );

var

        Percent : integer;

begin

   { do some code here }

   

   { Update the gauge }

   GaugeFunc( Percent );

end;



So, what this example tell us? It tell us that there is a private attribute

called FOnError that is a "callback" function. So, in your test function, if

a situation causes an error, you may call the OnError routine to signal that

an error happenned. The Assigned is nothing more than FOnError <> Nil.

Well, i think this may clear something in this topic. If not, or if i am

mistaken in something, tell me and we can debate on this more.


Terminate vs. PostMessage(Handle, wm_Close, 0, 0)

Question


Would someone care to elucidate on the differences and advantages or

disadvantages of closing applications with either of these two calls,

are they the same thing?  Do they both clean up properly?

Answer


A:

Calling application.terminate sets the value of 'terminated', while

closing the window directly does not. If you're doing direct WM

posts, this lets you trap the event.


How to detect program is already running

Question


How do I prevent my program to run which is already running?

Answer


A:

Use the hPrevInst variable. If it is 0 then there is no previous instance

otherwise your app is already running somewhere.



So in your project file (Project1.DPR or similar) add an if statement like



IF hPrevInst <> 0 THEN BEGIN

  Application.CreateForm(TForm1, Form1);

  Application.Run;

END;


TPolygon Object OnClick algorithm question

Question


I would like to make a polygon object that will allow the user to draw a

multiple side free form polygon.

I'm wondering if anyone has any ideas on how to write an algorithm to detect

if the user has clicked inside of the polygon for an OnClick Event.

Answer


A:

Check out the 2 WinAPI functions CreatePolygonRgn() and PtInRegion().

These will give you the capability you need. If you happen to have a

Compuserve account of susbscribe to Delphi Informant there is code in

the most recent issue on how to set up odd shaped mouse hot spots and

demonstrates how to use the above to functions.


Problems with GetSystemMetrics(SM_CYMENU)

Question


I'm trying to capture the height of the menu bar using

GetSystemMetrics(SM_CYMENU).  This works fine for a single-line

menu bar, which the WinApi help says it should.  My problem occurs

when the window is shrunk horizontally until the once-single-line

menu has to double-up on itself, becoming a double-line menu.

How can I determine the total height of the menu bar?

Answer


A:

Check if TForm.ClientOrigin (or ClientRect) is moved wrt TForm.Top, e.g.



  YDiff := ClientOrigin.Y - Top;



I find that this will become 42, 61, 80 with a wide enough menu to be

made into three lines. (Add 20 minus 1 for the border line which isn't there.)


Stuffing Keystrokes into buffer

Question


I need my application to be able to "stuff keystrokes" into the keyboard

buffer.

My application needs to be able to do this while minimzed and the

keystrokes should effect the active Window and appear "typed".

Answer


A:

{this proc interrogates the numlock key and sets the state}

{according to the value of bOn}



procedure TIndexForm.ToggleNumLockKey(bOn: Boolean);

var

  KeyState : TKeyBoardState;

begin

  GetKeyboardState( KeyState );

  if bOn then KeyState[VK_NUMLOCK] := 1

     else KeyState[VK_NUMLOCK] := 0;

  SetKeyboardState( KeyState );

end;


Insert / overwrite

Question


I've looked through help files and vcl source code for

components, but I haven't found any information about toggling

between insert and overwrite modes in components.  It seems

like a fairly easy thing to do (perhaps an api call?) but I'm

at a loss.

Answer


A:

    Here are a couple of routines that should help.  When

    testing, you'll have to watch out for the Delphi IDE's own

    use of Insert and Overwrite.  I'm not sure whether that

    setting is stored in the VK_INSERT entry of the Virtual key

    code table or not (and it may be reset on a return to the

    IDE).



    Also, it goes without saying that many Delphi components

    may well pay no attention to the setting of this key.



 function LowOrderBitSet(Int: integer): boolean;

{----------------------------------------------------------------}

{ Tests whether the low order bit of the given integer is set.   }

{----------------------------------------------------------------}

 const

   LowOrderBit = 0;

 type

   BitSet = set of 0..15;

 begin

   if LowOrderBit in BitSet(Int)

     then LowOrderBitSet := true

     else LowOrderBitSet := false;

 end;



 function InsertOn: boolean;

{----------------------------------------------------------------}

{ Returns the status of the Insert key.                          }

{----------------------------------------------------------------}

 begin

   if LowOrderBitSet(GetKeyState(VK_INSERT))

     then InsertOn := true

     else InsertOn := false

 end;



 procedure ToggleInsert;

{----------------------------------------------------------------}

{ Toggles the status of the Insert key.                          }

{----------------------------------------------------------------}

 var

   KeyBoardState: TKeyBoardState;

 begin

   GetKeyboardState(KeyBoardState);

   if InsertOn

     then KeyBoardState[VK_INSERT] := 0

     else KeyBoardState[VK_INSERT] := 1;

   SetKeyboardState(KeyBoardState);

 end;



A:

The reason why the Delphi component doesn't support overwrite is that it is

simply using the multi-line edit control that is one of the standard Windows

controls, and it does not support this capability directly.  However, there

is a simple technique that I got from one of the Borland SE's not too long

ago.  Here's what you do:



1.  Add a boolean variable to the private section of your form, and call it

InsertOn.

2.  Add an 'OnCreate' event handler to the form, to initialize InsertOn to

TRUE.

3.  Add a TLabel control to display whether insert is on or not (optional).

4.  Add an 'OnKeyDown' event handler to your TMemo or TDBMemo control, and

insert the following code:



procedure TForm1.Memo1KeyDown(Sender: TObject; var Key: Word;

  Shift: TShiftState);

begin

  if (Key = vk_Insert) and (Shift = []) then

  begin

    InsertOn := not InsertOn;

    if InsertOn then

      Label1.Caption := 'Insert'

    else

      Label1.Caption := 'Overwrite';

  end;

end;



5.  Add an 'OnKeyPress' event handler to your TMemo control, and code it like

this:



procedure TForm1.Memo1KeyPress(Sender: TObject; var Key: Char);

begin

  if (Memo1.SelLength = 0) and (not InsertOn) then

    Memo1.SelLength := 1;

end;



What happens is, if InsertOn is TRUE, then it selects one character so that

when the key gets inserted, it will be overwritten.  I think its a pretty

slick way to handle the problem.  Wish I could take credit for it!  Anyway,

this should take care of the problem.



I don't think there is any function called LowOrderBitSet in

Delphi--must have been his own function.  Also, as far as I know, the Insert

key is not a toggle in the same sense that the caps lock or num lock keys

are.  It is totally up to the app to decide what to do when it is pressed,

and if you want to make it toggle, you'll have to store the state of that

toggle yourself, the way I suggested (or some other way).


How can I trap a system error message

Question


I am writing an installation program for an application that I

have, but if the disk if not in the drive I get a system error

message [Cancel] [Retry], is it possible to trap this?

Answer


A:

 function DisketteDriveReady (DisketteDrive: char): boolean;

{----------------------------------------------------------------}

{ Returns true if specified Diskette drive [A/a or B/b] is ready }

{ with a diskette inserted, otherwise false.  From a Delphi-Talk }

{ posting by Per Ola Svensson    }

{----------------------------------------------------------------}

 var

   Drive: byte;

   SaveErrorMode: word;

 begin

   DisketteDriveReady := false;    {until proven otherwise}

   case DisketteDrive of

     'A', 'a':  Drive := 1;

     'B', 'b':  Drive := 2;

     else Exit;

   end; {case}

   SaveErrorMode := SetErrorMode(SEM_FAILCRITICALERRORS);

   if DiskFree(Drive) <> -1 then

     DisketteDriveReady := true;

   SetErrorMode(SaveErrorMode);

 end; {DisketteDriveReady}


Find window problem

Question


I am using FindWindow() to locate a window handle and I

am using PostMessage() to close the application.

The problem is that I can't seem to close Acrobat Reader

using FindWindow(nil, 'Acrobat Reader') and PostMessage()

whenever Acrobat Reader has a file opened.

Using winsight.exe, I noticed that Acrobat Reader changes

its classname and window title whenever a PDF file is

opened. How do I find Acrobat Reader's window handle and

send a message to close the application when the

classname and title change?

Answer


A:

You should use Getwindow() to cycle thru all the various windows and search

each one's 

name for acrobat reader, although this sounds like a chore it's really not

too tough and happens instantaneously when you run the program.



Here's the code to do it :

(* Function to get the handle of Adobe Acrobat, could be applied to any

 partial text window of a main program such as notepad, just change the

"Acrobat 

Reader" to the appropriate thing you're looking for, it will return 0 if the

window

wasn't found will return the handle if it was found     *)



Function GetAcrobatHwnd : word;



var

  hwndx :word;

  PString : Pchar;

  txtlength : integer;

  posit : byte;

begin{function}

 hwndx := Getdesktopwindow;

 GetWindow(hwndx,GW_CHild);

 While not done do

 begin

 Txtlength := GetWindowText(hwndx,PString,255);

 Posit := Pos("Acrobat Reader",Strpas(Pstring));

        If Posit > 0 then (* Acrobat was found, make the result the handle *)

        begin {if}  

        Result := hwndx;

        done := true;

        end;{if}

  if hwndx = Getwindow(hwndx,GW_Hwndlast) then (* Acrobat Isn't Running *)

    begin

    Result := 0;

    done := true;

    end;

hwndx := GetWindow(hwndx,GW_HWNDNEXT);

 end;{while}



end;{function GetAcrobatHwnd}



That function should cover it, let me know if you have any problems


How do I disable mouse cursor

Question


How do I disable mouse cursor on the image-component?

Answer


A:

You can also use the ShowCursor API Function set to false (-1). To enable

again call the function again with

True arguement (0).



But you must remember that the cursor will be unavailable to ALL windows

with this function! You must reset the

value if someone leaves the specific area of your Application that you want

the cursor disabled.

I would put it in the LostFocus event of my window or control or in test

cursor coords in the mousemove event to see if it

is out of the area. This is a little bit more work, but it lets Windows

handle the null cursor.



A:

I think that the simplest method to 'disable' the mouse is to create

a custom cursor wich is an empty image, then you assign this cursor

when the mouse is over the windowed control that you want (in your

case, a TImage component).

I use this technique to hide the mouse cursor in a program that

displays an animated image projected on a maxi-screen. Then I use a

right-click to show a menu that permits to re-display the cursor.

It works well and it's functional.



You should create a cursor with Resource Wokshop or similar resource

editors, and fit it in your RES. Then you must define a constant value

for your cursor that is greater then the standars Windows cursor

constant (for instance, 6 or 7):



const

   crNullCursor = 6;



Then in the create event, load the cursor:



Screen.Cursors [crNullCursor] := LoadCursor (hInstance, 'EMPTY');



Assuming that 'EMPTY' is the name for your custom cursor in the RES.

Then you can toggle for different Windows and custom cursor on every

windowed control, assigning the proper Cursor property.



TImage1.Cursor := crNullCursor;

TImage1.Cursor := crDefault;

etc...


Mouse cursor position

Question


I'd like to be able to get the actual

mouse co-ordinates though and not have rely on a mousedown event to get

them.  Anybody know how to do this?  Example,  I'd like to be able to have

a timer running and check the co-ordinates on a regular basis.  I assume

some Windows API calls are required here.

Answer


A:

You can use a MouseMove event. For example:



Var

  MyX, MyY : Integer;



Procedure Form1.Image1MouseMove(Sender : TObject...);

Var

  MyPoint : TPoint;

Begin

  If Timer1.Enabled Then 

  Begin

    MyPoint.X:=X;

    MyPoint.Y:=Y;

    MyPoint:=ClientToScreen(MyPoint);

    MyX:=MyPoint.X;

    MyY:=MyPoint.Y

  End 

End;



May not be elegant, but should be workable.


Shift Tab don't activate onexit event

Question


I've the following problem: When an user presses Shift-Tab, in a edit-box,

I don't want the OnExit event to be activated, but how ?? Does anybody has a

solution for this problem.

Answer


A:

Perhaps you could use code something like this:

Form1.Canvas.StretchDraw(Rect(0,0, 50,50), Image1.Picture.Graphic);



The function Rect() will take two points (x,y, x,y) and turn them into

a var of type TRect. The method Form1.ClientRect, simply returns a

TRect structure that can be used by StretchDraw. (Check out the help 

file for more details on these)



Here's a modified version, to stretch the bitmap from Image2 onto 

Image1. (Try the code out, a blank form with 2 TImages and a TButton, 

on which you can attach the following code, should work well ... :)



Image1.Picture.Bitmap.Canvas.StretchDraw(Rect(0,0, Image2.Width, 

                                                Image2.Height), Image2.Picture.Graphic);



To get the effect, a neat idea would be to make a scale factor, in 

say, an edit box, ranging from 0.01 to 1. The code would then look 

something along these lines:



procdure Button1.Click(Sender etc, can't remember the rest ... :(

var

  x,y: Integer;

  s: Double;  {Scale / Magnification factor}

  r: TRect;

begin

  s := StrToFloat(Edit1.Text);

  x := Trunc(Image2.Width * s + 0.5);   {Scale and round off with 0.5}

  y := Trunc(Image2.Height * s + 0.5);

  r := Rect(0,0, x,y);

  Image1.Picture.Bitmap.Canvas.StretchDraw(r, Image2.Picture.Graphic);

end;


Task ID

Question


I start a program with winexec and it gives me an instance. I need the task

handle (at least I think so) so I can reactivate it later if it still

exists(rather than starting another instance) I looked at

taskfirst/tasknext, but they are not working - I must not be initing the

structure properly but I can't figure out what i'm doing wrong. HELP!!!

basically, I want to start a program... later I may need it again... if it

is still running  (ie the user has not closed it) then I would like to make

it active - if I have a task handle then I could:

PostMessage(HWND_BROADCAST,WM_ACTIVATEAPP,01,taskid);

right?

Answer


A:

First I did some tests in my machine. I arrived to the following litle program

which works perfectly well:



program CrtApp;



uses WinCrt, winprocs, wintypes, toolhelp, sysutils;



var

	rslt			: bool;

	taskentry	: ttaskentry;



begin

	taskentry.dwsize := sizeof(taskentry);

	rslt := taskfirst(@taskentry);

	while rslt do begin

		with taskentry do

			writeln(format('Task: %6x  Hinstance: %6x', [htask, hinst]));

		if taskentry.hnext = 0 then

			break;

		rslt := TaskNext(@taskentry);

		end;

end.





Based on that, I suggest you try the following.



uses winprocs, wintypes, toolhelp, sysutils;



...

{ for a given instance return the task. Return 0 if failure }



Function instancetotask(myinstance : thandle) : thandle;

var

     temp      : thandle;

     rslt	: bool;

     taskentry	: ttaskentry;



begin

        result := 0

	taskentry.dwsize := sizeof(taskentry);

	rslt := taskfirst(@taskentry);

        repeat

          if not rslt then

               exit;

          if taskentry.hinst = myinstance then begin

               result := taskentry.htask;

               exit;

               end;

          if taskentry.hnext = 0 then

               exit;

          rslt := TaskNext(@taskentry);

          until false;

     end;


Setting the active window

Question


I am using a TTimer object to wait for an event and when that event occurs, I

want to display a dialog box to the user (probably something more elaborate

than MessageBox). But if my app is minimized or not the active window (for

example, if MS Word is the active app), my dialog box (or message box) does

not display.  I know my TTimer event procedure is working because I hear the

MessageBeep(0) that I put in there before I show my dialog box.

Answer


A:

I have tried this using a form of my own design, and it pops up in

front of the running application without having to resort to any API

stuff. Here's my timer event; as you can see it's not anything

special:



procedure TForm1.Timer1Timer(Sender: TObject);

begin

  Timer1.Enabled := False;

  MyDialog.ShowModal;

end;



It shows me the dialog no matter the state of my application

(not focused, minimized, whatever).


Updating Cursor immediately

Question


For example, if I change my cursor to a waiting clock cursor before

some time-consuming operations is executed, why isn't my waiting clock

cursor activated immediately? It's only activated after the event!

Answer


A:

Begin

   Try

      Screen.Cursor:=crHourGlass;

      ReportForm := TReportForm.Create(Application);

      Screen.Cursor:=crDefault;

      ReportForm.ShowModal;

      ReportForm.Free;

    Finally

      Screen.Cursor:=crDefault;

    end;

end;


Change System Menu

Question


How could I change the system menu so that it includes an item

like "register"?

Answer


A:

Here is a routine that should help:



 procedure AppendToSystemMenu (Form: TForm;

                               Item: string; ItemID: word);

{----------------------------------------------------------------}

{ Appends menu item to end of system menu of specified form and  }

{ to system menu of application's minimized icon.  For separator }

{ bar, use '-' for the Item, and 0 for the ItemID.               }

{----------------------------------------------------------------}

 var

   NormalSysMenu, MinimizedMenu: HMenu;

   AItem: array[0..255] of Char;

   PItem: PChar;

 begin

   NormalSysMenu := GetSystemMenu(Form.Handle, false);

   MinimizedMenu := GetSystemMenu(Application.Handle, false);

   if Item = '-' then

   begin

     AppendMenu(NormalSysMenu, MF_SEPARATOR, 0, nil);

     AppendMenu(MinimizedMenu, MF_SEPARATOR, 0, nil);

   end

   else

   begin

     PItem := StrPCopy(@AItem, Item);

     AppendMenu(NormalSysMenu, MF_STRING, ItemID, PItem);

     AppendMenu(MinimizedMenu, MF_STRING, ItemID, PItem);

   end

 end; {AppendToSystemMenu}



    To use the above routine, call it something like:



{ Add an item to the system menu: }

  AppendToSystemMenu(MainForm, '-', 0);  {Separator bar}

  AppendToSystemMenu(MainForm, '&Please Register...', 99);

  Application.OnMessage := MainForm.RegisterMsg;



    (Slightly to my surprise the above 3 lines work OK from the

    form's Create method).



    Then supply whatever you want to do when the user selects

    the new menu item in a method like:



procedure TMainForm.RegisterMsg (var Msg: TMsg;

                                 var Handled: boolean);

begin

  if Msg.Message = WM_SYSCOMMAND then

    if Msg.wParam = 99 then

       {Registration stuff}

end;


Move Mouse through Code

Question


How can you move the Mouse using code.

is there a global mouse variable?

maybe through application variable or screen variable

Is there delphi or do I have to use API what API would I use?

Can you restrict the range of the mouse?  (so if you drag it out side of a

rectangle it just hangs out along the border)

Answer


A:

GetCursorPos and SetCursorPos (in Windows API) are very easy to use.

See ClipCursor in the on-line help.


WinExec

Question


   wProg := WinExec('thingy.exe', SW_SHOW)

   while (still_running(wProg))

      Application.ProcessMessage;

   ...



I need this 'still_running' piece, any one have any ideas.

Answer


A:

still_running(wprog) == (GetModuleUsage(wprog) > 0)



But your own process could be terminated, so better use

  repeat Application.ProcessMessages

  until (GetModuleUsage(wProg) = 0) or Application.Terminated;



A:

     Try this code:



  var

    ProgramHandle: Word;

    PathName: PChar;



  ...



    ProgramHandle := WinExec(PathName, SW_SHOWNORMAL);

    While GetModuleUsage(ProgramHandle) <> 0 then

      Application.ProcessMessage;



  ...


How to drop down a combo box list

Question


I have a drop down combo box on a form. I need to be able to drop the

list down programmatically when (if) the user types in to the edit part

of the combo box. I am aware that there is a Windows message to do this,

but how do I use it?

Answer


A:

The message is CB_SHOWDROPDOWN and to use it:



	SendMessage(ComboBox1.Handle, CB_SHOWDROPDOWN, 1, 0) {Opens list}

	SendMessage(ComboBox1.Handle, CB_SHOWDROPDOWN, 0, 0) {Closes list}



A:

Procedure THebEnhancedDBComboBox.ShowList;

begin

  if GetWindowLong(Handle, gwl_Style) and cbs_DropDown = cbs_DropDown then

    SendMessage(Handle, cb_ShowDropDown, 1, 0);

end;



{ Hides the list of an associated drop-down combobox. }



procedure THebEnhancedDBComboBox.HideList;

begin

  if GetWindowLong(Handle, gwl_Style) and cbs_DropDown = cbs_DropDown then

    SendMessage(Handle, cb_ShowDropDown, 0, 0);

end;


Capturing the Maximize message

Question


I need to intercept the maximize system message and change the size of my

form manually (it's got a funky size. It resembles Delphi's main form in

size and behavior).  Right now, I have code in my OnResize event that

changes the size after the fact to what I want.  This makes a nasty flash,

even on my DX4/100.  This app is going to run on much slower machines (486

DX/33 or SX/25) and this flash as it redraws the form twice would be nasty

at that speed.  I tried writing my own handler for it assigned it to message

SC_MAXIMIZE.  This gave me a duplicate virtual method error (?).

Answer


A:

Respond to the WMGetMinMaxInfo message.  Pretty simple, some example

code is  below.  You don't get the flash, it just restricts how far

you can drag window borders when resizing, maximising, etc.  Set the

sizes to whatever you like.



private

    { Private declarations }

    procedure WMGetMinMaxInfo( var Message :TWMGetMinMaxInfo ); message WM_GETMINMAXINFO;



procedure TCCentre.WMGetMinMaxInfo( var Message :TWMGetMinMaxInfo );

begin

  with Message.MinMaxInfo^ do

  begin

    ptMaxSize.X := 640;                {Width when maximized}

    ptMaxSize.Y := 96;                {Height when maximized}

    ptMaxPosition.X := 0;             {Left position when maximized}

    ptMaxPosition.Y := 0;             {Top position when maximized}

    ptMinTrackSize.X := 500;           {Minimum width}

    ptMinTrackSize.Y := 96;           {Minimum height}

    ptMaxTrackSize.X := 640;           {Maximum width}

    ptMaxTrackSize.Y := 150;           {Maximum height}

  end;

  Message.Result := 0;                 {Tell windows you have changed

  minmaxinfo} inherited;

end;


Scroll Listbox programmatically

Question


I would like to scroll a list box programmatically by a button.

ie. when I click on the button, it's as though I've clicked on the

scrollbar arrow.

Answer


A:

Take a look at the LB_SETTOPINDEX Windows API message. Send it to the

desired listbox with the (zero-based) index in wParam.



Ex.

     SendMessage(ListBox.Handle,lb_SetTopIndex,10,0);



This will make the eleventh item appear as the first visible item.


Moving the cursor only in the x-axis

Question


Does anyone know how to trap the movement of the mouse cursor, in

such a way that the programmer can specify that only the x coord will

change ?

I am currently looking at the OnMouseMove event, but can't seem to

find a way to specify the Y coord.

I need to be able to hold the cursor on a horizontal line and not

allow it to move in the y axis.

Answer


A:

In your OnMouseMove, go something like:



   if (y<>0) and (lockY) then begin 

     GetMouseCoords(NewX,NewY);

     NewY := NewY + y;      {or should that be minus?}

     SetMouseCoords(NewX,NewY);

   end;



'lockY' is a variable you declare and set true when you want to do this 

type of control.



Substitute the real functions that get and set the mouse co-ordinates in

the relevant spots.


Send Messages to a control

Question


How do I send a window message to a control? I want to send

LVM_EDITLABEL to a TListView. Or does anyone know of any other way to

"manually" start editing of a label in a TListView?

Answer


A:

Use the NotifyControls(LVM_EDITLABEL) or...

  var

    msg : TMessage;

  begin

    msg.msg := LVM_EDITLABEL;

    msg.wParam := 0;

    msg.lParam := 0;

    msg.Result := 0;

    broadcast(msg);

  end;



please note that if you have a container such as a panel or page

control that contains other controls, the message won't be passed

through the container. You must code a message handler for each

container to receive and echo the message to the controls in that

container.


Previous Instance, FindWindow

Question


I'm having trouble detecting a previous instance of an application using

Delphi2.

Answer


A:

In Win32,  hInstance doesn't work.  Everytime you start an

application it has a complete and private address space that spans

4GB.  So, if you launch a program twice, the second one doesn't know

about the previous one (as it is in a different virtual address

space).  Again, all this is true only for 32-bit executables.

When you a launch 16 bit apps in Windows95 or WindowsNT, they all

share a common virtual machine, so you get instance handles.  Since

you were compiling the app with Delphi 1.x, your code worked.  Now in

the Delphi 2.0 you code is 'broken' beacuse your HPrevInst is always

zero.  If you still want to find a previous 'instance' (sic), you'll

have to resort to a different technique like searching for the main

window of the application.



A:

Another solution is to create a memory mapped file from the first instance.

If the file already exists then you know another instance is running.  I

don't have the Win32 API here, but if you search on "memory mapped file" you

should find it.


Waiting for an exec'd application to complete

Question


I'm looking for a component for Delphi 2.0 that will exec another

application and wait for it to complete.  I found one for Delphi 1.0, but

since it lacked sources it does me no good at all.

Answer


function WinExecAndWait32(FileName:String; Visibility : integer):integer;

var

  zAppName:array[0..512] of char;

  zCurDir:array[0..255] of char;

  WorkDir:String;



  StartupInfo:TStartupInfo;

  ProcessInfo:TProcessInformation;

begin

  StrPCopy(zAppName,FileName);

  GetDir(0,WorkDir);

  StrPCopy(zCurDir,WorkDir);

  FillChar(StartupInfo,Sizeof(StartupInfo),#0);

  StartupInfo.cb := Sizeof(StartupInfo);

  StartupInfo.dwFlags := STARTF_USESHOWWINDOW;

  StartupInfo.wShowWindow := Visibility;

  if not CreateProcess(nil,

    zAppName,                      { pointer to command line string }

    nil,                           { pointer to process security attributes }



    nil,                           { pointer to thread security attributes }

    false,                         { handle inheritance flag }

    CREATE_NEW_CONSOLE or          { creation flags }

    NORMAL_PRIORITY_CLASS,

    nil,                           { pointer to new environment block }

    nil,                           { pointer to current directory name }

    StartupInfo,                   { pointer to STARTUPINFO }

    ProcessInfo) then Result := -1 { pointer to PROCESS_INF }



  else begin

    WaitforSingleObject(ProcessInfo.hProcess,INFINITE);

    GetExitCodeProcess(ProcessInfo.hProcess,Result);

  end;

end;



A:

The following logic is fairly simple, but it works under both Delphi 1.0 and

2.0.



while FindWindow(NIL, ' 0 do

   Application.ProcessMessages ;

MessageDlg('Done!', mtInformation, [mbOK], 0) ;



A:

And if you want to process other Windows messages while executing the program

change the  WaitforSingleObject(ProcessInfo.hProcess,INFINITE); line to



      while WaitForSingleObject(ProcessInfo.hProcess, 100) = WAIT_TIMEOUT do

        Application.ProcessMessages;


_hread

Question


Can someone tell me how I would go about using the _hread win api with

delphi. Apparently it is not in the WinProcs unit. Might the

function be in a differnt unit?  I can use the _lread, _lwrite, ...,

but I want to be able to read the data into global mem in one pass.

Answer


_hread isn't declared in any Delphi file. You should declare it by

yourself using:



function _hread(FileHandle: Integer; Buffer: PChar; Bytes: LongInt):

LongInt; far; external 'KERNEL';



in your PAS file. It is also used internally in Delphi's function

FileRead. You can try FileOpen,FileRead and FileClose.


Manually drop-down a combobox

Question


Does anybody know a way of manually dropping down a combobox? In my

app I want the user to be able to type a value into a combobox. In the

OnExit event the value is to be validated and if it's not valid, the

dropdownlist of the combobox must appear. I don't want to use the

csDropDown style, because I want the user to be able to type the

value. The only problem is how to programmatically have the combobox

show its dropdown list.

Answer


SendMessage(DBComboBox1.Handle,CB_SHOWDROPDOWN,1,0);


Imitating Key Strokes

Question


Is there an easy way in Delphi to imitate keystrokes on a keyboard.

Answer


You can send a message to the window that must handle the key,  like:

 PostMessage(FWinControl.Handle, WM_KEYDOWN, VK_BACK, 1966081);


Mouse control within and area of the screen

Question


Anybody know if there is a way to limit mouse movement so that

the mouse can not be moved outside of a TPanel. I am trying to

write a system that requires no mouse movement outside the

upper left corner of the screen.

Answer


  Use the ClipCursor API function.  The only trick with it is to

  notice that its parameter is not a simple TRect but a pointer

  to a TRect, so you will have to use something like:

         var

           MyRect: TRect;

         ...

         ClipCursor(@MyRect);



  Also, remember to set the cursor free again at some stage with

         ClipCursor(nil);


Need WinProc

Question


The reason I need access to the WinProc is because I need to register

a custom Windows and Message and provide a message handler for this

message.  Is there some other way to do this within a component

without requiring a WinProc.

Answer


There should be no reason why you cant do the RegisterMessage during the

TComponent

Create method, just OverRide it. Also if all you are doing is posting the Same 

Message to yourself all the time and not to other windows there is no 

requirement to register the message

all you have to is define it so that your app knows what is. you can do that 

by making it a Const eg. MyMessage : WM_User + 1; {always start from WM_User 

plus what ever number}



Or in your MessageHandler Just test for it

eg if WM_User + 1 then.



As for the Message handler the code below should help you out.



constructor YourComp.Create(AOwner: TComponent);

begin

Inherited Create;

{hself is a variable defined in your private area}

hSelf := AllocateHwnd(OnMyMessage);

end;



procedure YourComp.OnMyMessage(var Msg: TMessage);

begin

  case Msg.Msg of

  WM_User + 1: begin

		ShowMessage('Got WM_User+1');

		end;

  WM_User + 2: begin

		ShowMessage('Got WM_User+2');

		end;  

  end;

end;



destructor YourComp.Destroy;

begin

  {Ensuring the handle we have allocated is de allocated}

  DeAllocatehWnd(hSelf);

  Inherited Destroy;

end;


Number of colors used in Windows

Question


How to make sure that windows is running at least using 256 colors video mode in

delphi program ?

So our program will not run in 16 colors.

Answer


Try this piece of code:



hDC := GetDC(0);



Bits := GetDeviceCaps(hDC, CAPS_BITSPIXEL);

PLANES := GetDeviceCaps (hDC, CAPS_PLANES);



DrvColours := (Bits * PLANES);

DrvColours := APowerB(2, DrvColours);

ReleaseDC (0, hDC);


EnumWindows()

Question


Can someone pass any information, or source along regarding

EnumWindows. Running D1.

Answer


  ENumWindows is described in D1's on-line WinAPI

  help, but you'll get much more helpful answers if you are more

  specific about what you are trying to achieve.



  As an example here is a bit if code that uses EnumWindows to

  locate a window containing a specified string in its title:



{function FindWindowHandle (HuntFor: string): HWnd;}

{----------------------------------------------------------------}

{ Hunts for a parent window with title containing the HuntFor    }

{ string.  Returns the window handle or 0 if none found.         }

{----------------------------------------------------------------}

    { The following indented code is logically a part of  }

    { FindWindowHandle but is placed here above the real  }

    { FindWindowHandle function heading as Borland do not }

    { allow nesting of callback functions.                }

    {-----------------------------------------------------}

     type

       PHuntRec = ^THuntRec;

       THuntRec = record

         HuntingFor: string;

         WindowFound: HWnd;

       end;



     function EnumWindowsFunc (WindowHandle: HWnd;

                         lParam: Longint): WordBool; export;

    {-----------------------------------------------------}

    { Callback function used by FindWindowHandle.         }

    {-----------------------------------------------------}

     var

       ATitle: array[0..255] of Char;

     begin

       GetWindowText(WindowHandle, PChar(@ATitle), 255);

       if StrHas(PHuntRec(lParam)^.HuntingFor,

                 StrPas(PChar(@ATitle))) then

       begin

         PHuntRec(lParam)^.WindowFound := WindowHandle;

         EnumWindowsFunc := false;     {stop looking}

       end

       else

         EnumWindowsFunc := true   {continue looking}

     end; {EnumWindowsFunc}



 function FindWindowHandle (HuntFor: string): HWnd;

 var

   Proc: TFarProc;

   HuntRec: PHuntRec;

 begin

   GetMem(HuntRec, SizeOf(THuntRec));

   HuntRec^.HuntingFor := HuntFor;

   HuntRec^.WindowFound := 0;

   Proc := MakeProcInstance(@EnumWindowsFunc, HInstance);

   EnumWindows(Proc, Longint(HuntRec));

   FreeProcInstance(Proc);

   FindWindowHandle := HuntRec^.WindowFound;

   FreeMem(HuntRec, SizeOf(THuntRec));

 end; {FindWindowHandle}


Undo in a memo field

Question


How can I do undo in a memo?

Answer


  If you have a pop-up menu in a TMemo, and put shortcuts 

on it for the Cut,Copy, Paste, then you can handle those 

events, and call CuttoClipBoard, CopytoClipBoard, etc.



  However, if you put an Undo option onto your pop-up menu 

(normally Ctrl-Z) how do you instruct the TMemo to do the Undo?

If the built-in undo is sufficient, you can get it easier than

a Ctrl+Z:



    Memo1.Perform(EM_UNDO, 0, 0);



 To check whether undo is available so as to enable/disable 

an undo menu item:



    Undo1.Enabled := Memo1.Perform(EM_CANUNDO, 0, 0) <> 0;




Terminate all running applications

Question


How to terminate all running applications?

Answer


{

  A word of caution, before you run this for the first time, make sure

  that you save it and anything else that may have some pending data.

}

procedure TForm1.ButtonKillAllClick(Sender: TObject);

var

  pTask   : PTaskEntry;

  Task    : Bool;

  ThisTask: THANDLE;

begin

  GetMem (pTask, SizeOf (TTaskEntry));

  pTask^.dwSize := SizeOf (TTaskEntry);



  Task := TaskFirst (pTask);

  while Task do

  begin

    if pTask^.hInst = hInstance then

      ThisTask := pTask^.hTask

    else

      TerminateApp (pTask^.hTask, NO_UAE_BOX);

    Task := TaskNext (pTask);

  end;

  TerminateApp (ThisTask, NO_UAE_BOX);

end;




How to keep apps iconized

Question


How to keep applications iconized?

Answer


1.  You must set WindowState to wsMinimized in the form's properties.



2.  In the private section of the form object's declaration, put:



      PROCEDURE WMQueryOpen(VAR Msg : TWMQueryOpen); message WM_QUERYOPEN;



3.  In the implementation section, put this method:



      PROCEDURE TForm1.WMQueryOpen(VAR Msg : TWMQueryOpen);

      begin

        Msg.Result := 0;

      end;



That's it! The form will always remain iconic. 




Trapping WM_ENDSESSION message

Question


How to trap WM_ENDSESSION message?

Answer


The problem seems to be that when you close down Windows, it will first

send a WM_QueryEndSession message to all running top-level windows. This

is handled and processed correctly by the TForm object in VCL.



Then assuming that all applications indicated that it was ok to close down,

Windows will send WM_EndSession messages to all windows. This message is

not handled by VCL. The application is simply brought down with a bang.

No windows are closed, no destructor called and no exit procedures called.



The solution is to handle the WM_EndSession message yourself. There are

several ways of handling messages in Delphi, but the only reliable way

of handling the WM_ENDSESSION is to use the HookWindow method of

Application.



In the message handler, check to see if the message is a WM_ENDSESSION.

If so, we should close down the application. We could have called the

Close method of the main window, but the Windows API documentation states

that the system might go down anytime after return from the WM_ENDSESSION,

and a posted WM_QUIT message might never arrive to the application.



The solution is to simply call Halt instead. This will call all registred

exit procedures, including the ones in Controls and DB units. These will

free the application and screen objects and take the BDE down correctly.



A simple example follows:



unit Tst2u;



interface



uses

  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,

  Forms, Dialogs, Grids, DBGrids, DB, DBTables;



type

  TForm1 = class(TForm)

    DataSource1: TDataSource;

    Table1: TTable;

    DBGrid1: TDBGrid;

    procedure FormCreate(Sender: TObject);

  private

    { Private declarations }

    function HookProc(var Message: TMessage): boolean;

  public

    { Public declarations }

  end;



var

  Form1: TForm1;



implementation



{$R *.DFM}



const

  FlagFileName = 'C:\Flag.Fil';



procedure CreateFlagFile;

var

  F: System.Text;

begin

  System.Assign(F, FlagFileName);

  System.Rewrite(F);

  Writeln(F, 'This is a dummy flag file');

  System.Close(F);

end;



procedure KillFlagFile;

var

  F: File;

begin

  System.Assign(F, FlagFileName);

  System.Erase(F);

end;



procedure MyExitProc; far;

begin

  KillFlagFile;

end;



procedure TForm1.FormCreate(Sender: TObject);

begin

  Application.HookMainWindow(HookProc);

end;



function TForm1.HookProc(var Message: TMessage): boolean;

begin

  Result := false;

  if Message.Msg = WM_EndSession then

  begin

    if WordBool(Message.wParam) then

    begin

      { Windows is closing down - clean up!! }



      { This should execute all ExitProcs, close windows and call destructors... }

       Halt; { This works! }



      { This should close things down properly,

        but do we have enough time to handle any posted messages before Windows

        is already down??  This will result in a PostQuitMessage that might

        never arrive!}

{      Close;} { This doesn't always work - avoid it }

    end;

  end;

end;



initialization

  CreateFlagFile;

  AddExitProc(MyExitProc);

end.



This unit demonstrates that the exit procedures are called when closing

the app normally and when closing down Windows and using HookMainWindow.

Without the HookMainWindow call, the exit proc will not be called. This

is specially important for DB applications. Without the Halt, LCK files

will not be deleted, buffers might not be flushed, changes posted and

so on.




Restarting Windows

Question


How to restart Windows?

Answer


There are two documented functions in the Windows API for restarting

Windows: ExitWindows(), and ExitWindowsExec().  (See the Windows API help

for details on both.) A common misconception is that the Program Manager DDE

macro call "[Reload()]" is for restarting Windows; it is not!



The call ExitWindows( 0, EW_RESTARTWINDOWS ) is _supposed_ to shut down

Windows, then bring it back up.  I've had no luck, though, from inside a

Delphi app.  It just shuts down Windows and gives me a DOS prompt.



ExitWindowsExec was built so that you could shut down Windows, execute a DOS

app (to replace Windows-critical DLL's, for example), and then bring Windows

hack up.  I have discovered that you simply need to pass a bad executable

name, and ExitWindowsExec performs exactly as ExitWindows was supposed to!



For example, the last few lines of an installation application may be:



        if (MessageDlg( 'The installation was successful!  You must now ' +

                       'restart Windows.  Do this now?', mtInformation,

                       [mbYes, mbNo], 0) = mrYes) then begin

           ExitWindowsExec( BOGUS_EXE, Nil );

        end;



where BOGUS_EXE is declared something like



        const

           BOGUS_EXE = 'zyxwvuts.exe';




Automate memo or window scrolling

Question


How to automate memo or window scrolling?

Answer


procedure TForm1.Edit1KeyDown(Sender: TObject; var Key: Word;

  Shift: TShiftState);

begin

  if Key = VK_F8 then

    SendMessage(Memo1.Handle,  { HWND of the Memo Control }

                WM_VSCROLL,    { Windows Message }

                SB_PAGEDOWN,   { Scroll Command }

                0)             { Not Used }

  else if Key = VK_F7 then

    SendMessage(Memo1.Handle,  { HWND of the Memo Control }

                WM_VSCROLL,    { Windows Message }

                SB_PAGEUP,     { Scroll Command }

                0);            { Not Used }

end;




Virtual key values

Question




Answer


vk_LButton   = $01;

vk_RButton   = $02;

vk_Cancel    = $03;

vk_MButton   = $04;   { NOT contiguous with L & RBUTTON }

vk_Back      = $08;

vk_Tab       = $09;

vk_Clear     = $0C;

vk_Return    = $0D;

vk_Shift     = $10;

vk_Control   = $11;

vk_Menu      = $12;

vk_Pause     = $13;

vk_Capital   = $14;

vk_Escape    = $1B;

vk_Space     = $20;

vk_Prior     = $21;

vk_Next      = $22;

vk_End       = $23;

vk_Home      = $24;

vk_Left      = $25;

vk_Up        = $26;

vk_Right     = $27;

vk_Down      = $28;

vk_Select    = $29;

vk_Print     = $2A;

vk_Execute   = $2B;

vk_SnapShot  = $2C;

vk_Copy      = $2C not used by keyboards }

vk_Insert    = $2D;

vk_Delete    = $2E;

vk_Help      = $2F;

vk_A thru vk_Z are the same as their ASCII equivalents: 'A' thru 'Z' }

vk_0 thru vk_9 are the same as their ASCII equivalents: '0' thru '9' }

vk_NumPad0   = $60;

vk_NumPad1   = $61;

vk_NumPad2   = $62;

vk_NumPad3   = $63;

vk_NumPad4   = $64;

vk_NumPad5   = $65;

vk_NumPad6   = $66;

vk_NumPad7   = $67;

vk_NumPad8   = $68;

vk_NumPad9   = $69;

vk_Multiply  = $6A;

vk_Add       = $6B;

vk_Separator = $6C;

vk_Subtract  = $6D;

vk_Decimal   = $6E;

vk_Divide    = $6F;

vk_F1        = $70;

vk_F2        = $71;

vk_F3        = $72;

vk_F4        = $73;

vk_F5        = $74;

vk_F6        = $75;

vk_F7        = $76;

vk_F8        = $77;

vk_F9        = $78;

vk_F10       = $79;

vk_F11       = $7A;

vk_F12       = $7B;

vk_F13       = $7C;

vk_F14       = $7D;

vk_F15       = $7E;

vk_F16       = $7F;

vk_F17       = $80;

vk_F18       = $81;

vk_F19       = $82;

vk_F20       = $83;

vk_F21       = $84;

vk_F22       = $85;

vk_F23       = $86;

vk_F24       = $87;

vk_NumLock   = $90;

vk_Scroll    = $91;




Getting DOS and Windows version numbers

Question


How can I get the Windows or DOS version numbers?

Answer


The API call GetVersion will do it, but the information is

encrypted into a longint.  Here is how to get and decrypt the information:



  Type

    TGetVer = record

      WinVer,

      WinRev,

      DosRev,

      DosVer: Byte;

    end;



  const

    VerStr = '%d.%d';



  procedure TForm1.Button1Click(Sender: TObject);

  var

    AllVersions: TGetVer;

  begin

    AllVersions := TGetVer(GetVersion);

    Edit1.Text := Format(VerStr, [AllVersions.WinVer, AllVersions.WinRev]);

    Edit2.Text := Format(VerStr, [AllVersions.DOSVer, AllVersions.DOSRev]);

  end;



Note1:  The values that windows displays for the versions and the values

that it returns through its API call are not always the same.  e.g.  The

workgroup version displays as 3.10 rather than 3.11.



Note2: Win32 applications should call GetVersionEx rather than GetVersion.





DISCLAIMER: You have the right to use this technical information

subject to the terms of the No-Nonsense License Statement that

you received with the Borland product to which this information

pertains.




Flashing an applications's title bar and/or icon

Question


How can I make the title of my app flash? I want to be able to notify the user 

that a process is completed while the app is minimized or maximized. 

Answer


It's easy... use the FlashWindow API function.  FlashWindow accepts two 

parameters. The first is the handle of the window to flash (i.e., change its 

status from active to inactive, or vice versa).  The second is a boolean 

indicating whether to flash the window (True) or return it to its original 

state (False).  



The best way to use FlashWindow is in conjunction with a timer.  The following 

syntax in your timer's OnTimer event handler will flash the current window:



procedure TForm1.Timer1Timer(Sender: TObject);

begin

     FlashWindow(Handle, True) ;

end;



However, if your application is minimized and you want the icon to flash, you 

need to make a slightly different call to FlashWindow.  Instead, you would pass 

the handle of your application (the global Application variable), which manages 

the icon.



procedure TForm1.Timer1Timer(Sender: TObject);

begin

     FlashWindow(Application.Handle, True) ;

end;



Of course, you can make both calls together without any ill effects.




Determining number of lines a memo can show

Question


How can I tell how many lines a memo is capable of showing? 

Answer


Here is the short and elegant way that works (most of the 

time):



function TForm1.MemoLinesShowing(memo: TMemo): integer;

var

  R: TRect;

begin

  Memo.Perform(EM_GETRECT, 0, Longint(@R));

  Result := (R.Bottom - R.Top) div Canvas.TextHeight('XXX');

end;



The problem with this code is that the TForm and the TMemo must 

both be using the same font.  If the fonts are different, then 

the calculations are not accurate.



You have to retrieve the font height by selecting it into a 

device context. The reason you cannot use the font Height 

provided by Delphi is because Delphi caches the font infomation 

but doesn't acutally select the font into the DC (canvas) until 

it is actually going to draw something. This occurs in the 

painting event of the memo. 



To get around this problem,  you can get the memo's device 

context using the Windows API and  get the font information 

from the device context to calculate the text height. 



The function below illustrates this process:



function TForm1.MemoLinesShowingLong(Memo: TMemo): integer;

Var

  Oldfont: HFont;  {the old font}

  DC: THandle;     {Device context handle}

  i: integer;      {loop variable}

  Tm: TTextMetric; {text metric structure}

  TheRect: TRect;

begin

  DC := GetDC(Memo.Handle); {Get the memo's device context}

  try

   {Select the memo's font}

    OldFont := SelectObject(DC, Memo.Font.Handle);

    try

      GetTextMetrics(DC, Tm); {Get the text metric info}

      Memo.Perform(EM_GETRECT, 0, longint(@TheRect));

      Result := (TheRect.Bottom - TheRect.Top) div

         (Tm.tmHeight + Tm.tmExternalLeading);

    finally

      SelectObject(DC, Oldfont); {Select the old font}

    end;

  finally

    ReleaseDC(Memo.Handle, DC); {Release the device context}

  end;

end;




Exiting Windows from within a Delphi app

Question


How to exiting Windows from within a Delphi app?

Answer


There are occasionally situations where you may need to force the user to exit 

or restart Windows from within your Delphi app. It can be done fairly easily. 



The syntax varies dependent upon whether you are using Windows 3.x or 

Windows 95/NT.  If you are using Windows 3.x, you will want to use the 

ExitWindows API function. ExitWindows accepts two parameters. The second 

parameter must always be zero. The first parameter can be zero, which will 

exit Windows, or either of the following two self-explanatory constants: 

ew_RebootSystem or ew_RestartWindows. (Note that this is the opposite of what 

the Windows API help file tells you, namely, that the first parameter should 

always be zero. Do not be fooled!)



If you are using Windows 95/NT, you should use the similar but different 

ExitWindowsEx API function. Like ExitWindows, ExitWindowsEx also accepts two 

parameters, the second of which must always be zero. To reboot the system and 

restart, pass ewx_Reboot as the first parameter. You may also pass ewx_PowerOff 

to shut down the system. You may also combine one of those two parameters with 

ewx_Force, which forces all processes to terminate without user interaction 

(i.e., even if they do not respond, shut them down without giving the user the 

customary #no response# dialog). NOTE: The ExitWindows function does exist in 

Windows 95/NT, but it can only be used to log off the current user. 

ExitWindowsEx is far more flexible.



Additional Windows 95/NT Information: If you want your app to be able to shut 

down or restart Windows, it must have the SE_SHUTDOWN_NAME privilege enabled. 

(I found this to be the case by default, but as they say, your mileage may vary.)  

This can be accomplished by using the AdjustTokenPrivileges API function, which 

is fully documented in the Win32 Programmer's Reference which accompanies 

Delphi 2.0.


Simulate sending key to own application

Question


I've a situation where I need to simulate as though the user

has pressed a RETURN key on my application.

Answer


You can send a message to the window that must handle the key,  like:

  PostMessage(FWinControl.Handle, WM_KEYDOWN, VK_BACK, 0);

for the backspace case.


ExitWindows

Question


Does anyone know how to access the function ExitWindows in

User.exe. I would like to use this function to restart windows

without restarting the computer.

Answer


  Here are examples of how to restart Windows and also how to

  reboot the system:



    procedure TMainForm.RestartWindowsBtnClick(Sender: TObject);

    begin

      if not ExitWindows(EW_RestartWindows, 0) then

        ShowMessage('An application refused to terminate');

    end;



    procedure TMainForm.RebootSystemBtnClick(Sender: TObject);

    begin

      if not ExitWindows(EW_RebootSystem, 0) then

        ShowMessage('An application refused to terminate');

    end;





  The ExitWindows function has always been wrongly documented -

  Microsoft got it wrong in their documents and every one else

  followed along with the incorrect info.  I believe the correct

  definition is:



    function ExitWindows (dwReturnCode: Longint;

                          Reserved: Word): Bool;


System Menu

Question


How do you add something to the system menu, say something

like an about command or something of the the type.

Answer


A:

Here's a procedure that will do it:



 procedure AppendToSystemMenu (Form: TForm;

                               Item: string; ItemID: Word);

{----------------------------------------------------------------}

{ Appends menu item to end of system menu of specified form and  }

{ to system menu of application's minimized icon.  To append a   }

{ separator bar start the item with '-' (and use 0 for ItemID).  }

{----------------------------------------------------------------}

 var

   NormalSysMenu, MinimizedMenu: HMenu;

   AItem: array[0..255] of Char;

   PItem: PChar;

 begin

   NormalSysMenu := GetSystemMenu(Form.Handle, false);

   MinimizedMenu := GetSystemMenu(Application.Handle, false);

   if StartsWith('-', Item) then

     AppendMenu(NormalSysMenu, MF_SEPARATOR, 0, nil);

     AppendMenu(MinimizedMenu, MF_SEPARATOR, 0, nil);

   end

   else

   begin

     PItem := StrPCopy(PChar(@AItem), Item);

     AppendMenu(NormalSysMenu, MF_STRING, ItemID, PItem);

     AppendMenu(MinimizedMenu, MF_STRING, ItemID, PItem);

   end

 end; {AppendToSystemMenu}





  The StartsWith function that is used above is defined:



 function StartsWith (const StartString, theString: string)

                     : Boolean;

{----------------------------------------------------------------}

{ Tests whether or not theString starts with the StartString.    }

{ N.B. Case sensitive.                                           }

{----------------------------------------------------------------}

 begin

   if Copy(theString, 1, length(StartString)) = StartString then

     StartsWith := True

   else

     StartsWith := False

 end; {StartsWith}



A:

Create a new form and add the following:



type

  TForm1 = class(TForm)

  private

    { Private declarations }

  public

      procedure WinMsgHandler( var Msg : TMsg; var Handled : Boolean );

    { Public declarations }

  end;



const

       WM_ABOUT = WM_USER + 1;   { About message }



IMPLEMENTATION

procedure TForm1.WinMsgHandler( var Msg : TMsg; var Handled : Boolean );

begin

   If Msg.Message = WM_SYSCOMMAND then

   begin

       if Msg.wParam = WM_ABOUT then Showmessage('Hello World!!');

   end;

end;



In the forms create method you should add the following:-



   Application.OnMessage := WinMsgHandler; {Use my message handler}

   AppendMenu( GetSystemMenu( Self.Handle, False ),

       MF_SEPARATOR, 0, ''); {Append our new value}

   AppendMenu( GetSystemMenu( Self.Handle, False ), MF_BYPOSITION,

       WM_ABOUT, '&Hello' );



A:

unit Sysmenuu;



interface



uses

  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics,

  Controls, Forms, Dialogs;



type

  TForm1 = class(TForm)

    procedure FormCreate(Sender: TObject);

  private

    { Private declarations }

    procedure AppOnMessage(VAR Msg: TMsg; VAR Handled: Boolean);

  public

    { Public declarations }

  end;



var

  Form1: TForm1;



implementation



{$R *.DFM}



CONST SC_UDF = $EFF0;



procedure TForm1.FormCreate(Sender: TObject);

begin

  AppendMenu(GetSystemMenu(Handle, False), { API call; see API Help }

    MF_STRING, SC_UDF, '&About');

  AppendMenu(GetSystemMenu(Application.Handle, False),

    MF_STRING, SC_UDF, '&About');

  Application.OnMessage := AppOnMessage;

end;



procedure TForm1.AppOnMessage(VAR Msg: TMsg; VAR Handled: BOolean);

VAR

  Hf, Ha : hMenu;

  Checkd : Boolean;

CONST

  NuFlag : ARRAY[Boolean] OF Word = (MF_CHECKED, MF_UNCHECKED);

  NuHWnd : ARRAY[Boolean] OF HWnd = (HWND_TOPMOST, HWND_NOTOPMOST);

BEGIN

  IF Msg.Message <> WM_SYSCOMMAND THEN Exit;

  IF Msg.wParam AND $FFF0 <> SC_UDF THEN Exit;



  { show your About Dialog }



END;



end.


GetModuleFileName

Question


If I'm using GetModuleFileName, I can't get it working. I'm assuming that

the problem is the hInstance in the first parameter. So let's say I wanted

to get the Module filename of the SysListView32....on my computer, it

has the handle of 168 all the time, so I'm assuming it doesn't change, so this

is my code basically:



stuff := GetWindowLong(168, GWL_hINSTANCE);

GetModuleFileName(stuff, buf, 100);



where buf is pchar...



Now what's the problem here?  I get the hInstance don't I?  Why isn't this

working?

Answer


procedure TForm1.Button1Click(Sender: TObject);

var

   szFileName : array[0..49] of char;

   szModuleName : array[0..19] of char;

   iSize : integer;

begin

   StrPCopy(szModuleName, 'NameOfModule');

   iSize := GetModuleFileName(GetModuleHandle(szModuleName),szFileName,

                  SizeOf(szFileName));

   if iSize > 0 then

      ShowMessage('Full path name is : ' + StrPas(szFileName))

   else

      ShowMessage('Path of module not found');

end;


CM_MOUSELEAVE

Question


I was wondering if there is a Windows message that is sent to a component

when a mouse is moved over it and when the mouse is moved out from it's

space.  For example, when the mouse moves over a TPanel and also when the

mouse leaves the TPanel.

Answer


You can also take advantage of two Delphi predefined messages,

CM_MOUSEENTER and CM_MOUSELEAVE.  Below is a brief piece of code showing

one way to do it.  I have tried it and it worked fine with TSpeedButtons. It

should normally work with TPanels as well.  Try it yourself!



unit SomeForm;



interface

type

  TSomeForm = class(TForm)

    private

      procedure CMMouseEnter(var Msg: TMessage); message CM_MOUSEENTER;

      procedure CMMouseLeave(var Msg: TMessage); message CM_MOUSELEAVE;

  end;



implementation



procedure TSomeForm.CMMouseEnter(var Msg: TMessage);

var

  anObject :        TObject;

begin

  { anObject is the control over which the mouse is right now }

  anObject := TObject(Msg.lParam);

  if anObject <> nil then begin

    { First, you must find WHICH is the control under the mouse cursor, }

    { then, determine what action to do, etc... }

  end;

end;



procedure TSomeForm.CMMouseLeave(var Msg: TMessage);

begin

  { anObject is the control which the mouse has just gone out of }

  anObject := TObject(Msg.lParam);

  if anObject <> nil then begin

    { First, you must find WHICH is the control }

    { the mouse cursor has just left, }

    { then, determine what action to do, etc... }

  end;

end;



end.


Close    To Top
  • Prev Article-Programming:
  • Next Article-Programming:
  • Now: Tutorial for Web and Software Design > Programming > delphi > Programming Content
    Photoshop Tutorial
     

    Special Effect

      3D Effect
      Photoshop Articles
    Programming Tutorial
     

    C/C++ Tutorial

      Visual Basic
      C# Tutorial
    Database Tutorial
     

    MySQL Tutorial

      MS SQL Tutorial
      Oracle Tutorial
    Geek Tutorial
     

    Blogging Tutorial

      RSS Tutorial
      Podcasting Tutorial
    Graphic Design Tutorial
      Coreldraw Tutorial
      Illustrator Tutorial
      3D Tutorials
    Webmaster Articles
     

    Domain Service

      Web Hosting
      Site Promotion
    Java Tutorial/ Articles
     

    Java Servlets

      JavaEE Tutorial
     

    JavaBeans Tutorial

    XML Tutorial/ Articles
     

    XML Style

      AJAX Tutorial
      XML Mobile
    Flash Tutorial/ Articles
     

    Flash Video

      Action Script
      Flash Articles
    OS Tutorial/ Articles
      Linux Tutorial
      Symbian Tutorial
      MacOS Tutorial
    Personal Tech
      Hardware Tutorial
      Software Tutorial
      Online Auction