Archive

Archive for the ‘System’ Category

How to Determine if There is Anything in the Clipboard

December 15th, 1999 m3Rlin 3 comments

When creating a text editor (or any other kind of program that uses the Clipboard you always insert code to determine if there is anything to copy or cut and to update the menus. Well, you should also do this for the paste function. The whole idea is based on Windows messages and is very easy.

Here’s the code. The sample code contains a form named MainForm and a paste menu item named miEditPaste.

uses

  Clipbrd;

...

type

  TMainForm = class(TForm)

    procedure FormCreate(Sender: TObject);

    procedure FormDestroy(Sender: TObject);

  private

    hClipboardOwner: HWnd;

    { The messages used for determing the Clipboard contents }

    procedure WMChangeCBChain(var Msg: TWMChangeCBChain); message WM_CHANGECBCHAIN;

    procedure WMDrawClipboard(var Msg: TWMDrawClipboard); message WM_DRAWCLIPBOARD;

...

Add this code to your form’s OnCreate event. It will let Windows know we want to know what’s going on with the Clipboard.

...

  hClipboardOwner := SetClipboardViewer(Handle);

...

Add this code to your form’s OnDestroy event. This will free us from the Clipboard chain.

...

  ChangeClipboardChain(Handle, hClipboardOwner);

...

This is the code for the message handling:

(* The WM_CHANGECBCHAIN message is sent to the first window in the clipboard viewer chain when
** a window is being removed from the chain
*)

procedure TMainForm.WMChangeCBChain(var Msg: TWMChangeCBChain);
begin
  if Msg.Remove = hClipboardOwner then
    hClipboardOwner := Msg.Next
  else
    SendMessage(hClipboardOwner, WM_CHANGECBCHAIN, Msg.Remove, Msg.Next);
  Msg.Result := 0; { The message has been taken care of }
end;

(* The WM_DRAWCLIPBOARD message is sent to the first window in the clipboard viewer chain when
** the content of the clipboard changes. This enables a clipboard viewer window to display the new
** content of the clipboard
*)

procedure TMainForm.WMDrawClipboard(var Msg: TWMDrawClipboard);
begin
  { Let the next viewer in the chain know that Clipboard has been changed }
  SendMessage(hClipboardOwner, WM_DRAWCLIPBOARD, 0, 0);
  Msg.Result := 0; { The message has been taken care of }
  { Insert you code here... }
  miEditPaste.Enabled := Clipboard.HasFormat(CF_TEXT); { Enabled the menu item only if there is text in the Clipboard }
end;

How to Make the Whole Form Behave Like the Title Bar

December 15th, 1999 m3Rlin No comments

Sometimes you want to create a fancy looking form from a bitmap, like WinAMP or K-J?fol. This part isn’t too hard. All you have to do is make a cool graphic, use the TImage component and set the form’s border style to bsNone. Well, all’s good until we want to move the form… Since there is no title bar there may be a problem with this:) Well, as you should already know Delphi can get over any problem. All we have to do is manually take care of the WM_NCHITTEST Windows message.

In this example a TImage component named imgTitle will act like the form’s title bar.

uses
  Messages;
...
  public
    procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST;
  end;
...
procedure TForm1.WMNCHitTest(var Message: TWMNCHitTest);
var
  P: TPoint;
begin
  inherited;
  P := ScreenToClient(SmallPointToPoint(Message.Pos));
  with imgTitle do
    if (P.X >= Left) and (P.X < Left + Width) and (P.Y >= Top) and (P.Y < Top + Height) then
      Message.Result := htCaption;
end;