INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Jobs

A Mouse Over Form

A Mouse Over Form

(OP)
One of the consistent problems I've run into (a couple of projects now) is the need to show a small form upon an event which is on top of other windows, and then dismisses itself after a certain amount of time. The main reason is to be able to show more information (even some graphical data) than a hint text.

Any ideas on how to solve this? The main thing I've done is as follows, using a button to simulate what I'm trying to do:

CODE

// form1
procedure TForm1.Button1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  Form2.Show;
  Button1.OnMouseMove := nil;
end;

// form2
procedure TForm2.FormCreate(Sender: TObject);
begin
  Timer1.Enabled := true;
end;

procedure TForm2.Timer1Timer(Sender: TObject);
begin
  Form2.Close;
  Form1.Button1.OnMouseMove := Form1.Button1MouseMove;
end; 

The major problems:
1. Getting the event to fire once and only once, no matter what? I'm not sure what I did is the best way from an "extensible" standpoint, but it seems to work.
2. Making sure the window shows no matter what. If the application happens to not have focus (which is realistic given these apps, as they are notification area programs), the extended hint window (form2) has a way of being buried or not shown at all.
3. Since they're notification area programs, the other unrelated problem is one of positioning the form. One problem I noticed on varying windows platforms is that SHAppBarMessage fails on the older ones (I have intentions on making one of the projects as universal as possible). I couldn't find any documentation on how to find the app bar outside of that API, so I'm wondering am I stuck here or is there another way to do it?

Ideas?

RE: A Mouse Over Form

(OP)
Since I made a little better test representative of what my projects are, another problem:

4. The window happens to be pretty disruptive when the application does have focus. So I guess, the main thing is to get a form that acts like a hint text, shows the notification it needs to show, and just gets out of the way.

RE: A Mouse Over Form

(OP)
5. One problem hearkening to #3, but different.

Link to image

It seems something's reporting incorrectly somewhere or I'm not considering something, as I want the form to sit directly on the appbar.

(sorry, the link parsing here doesn't seem to work right to show the image, just click on the link)



RE: A Mouse Over Form

Did you know you can upload images to TT now?lol

So to summarize your question are:

- how to find the taskbar to determine the correct position for your notification window
- show that window without stealing focus

Am I correct?

P.S.: why do you not adhere to the windows standard and use a tray icon that show a balloon tip?

/Daddy

-----------------------------------------------------
Helping people is my job...

RE: A Mouse Over Form

(OP)
Uploading the image did not work correctly. As did linking directly to it to show it on the page, as the link parsing code is off here.

>how to find the taskbar to determine the correct position for your notification window

Which I *can* do with the SHAppBarMessage API as detailed in the link above. The problem is that the call fails on older OSes. I thought of looking for Shell_TrayWnd and then finding the bounding rectangle, but I'm not sure how universal *that* is. In terms of where the line is that I can expect the proper API call to work, is perhaps the question as documentation for older Windows versions has a way of disappearing very quickly. Ironically, the code behind the specific project I have in mind for the older OSes is so rudimentary that it worked for *all* Windows versions ever made, but the problem is one of display.

>show that window without stealing focus

This was problem #2, for which I'm doing this:

CODE

SetFocus;
   SetForegroundWindow(Handle);
   BringToFront; 

It works great if the application has focus, but if it doesn't, the window always shows up behind the others.

Other issues are more appearance related (#5) and whether I'm doing it the best way (#1). The appearance related stuff might iron itself out once I take away the border and add a panel bevel.

>why do you adhere to the windows standard and use a tray icon that show a balloon tip?

I guess this should be "why do you not"? Anyway, the balloon tip has a text limit on it too like the hints (and don't think you can show graphics). Besides, I've seen different apps be able to do what I'm looking to do, so I can't say it's out of the question. Just not been able to pull it off properly.

RE: A Mouse Over Form

2
It seems I happen to have this feature in one of my applications:

CODE

unit u_frm_alertwindow;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TFrm_alert = class(TForm)
    Panel1: TPanel;
    Button1: TButton;
    Lbl_alert: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
    FT5CallId : Integer;
    FHwnd     : THandle;
  protected
    procedure CreateParams(var Params: TCreateParams); override;
    procedure CreateWindowHandle(const Params: TCreateParams); override;
  public
    { Public declarations }
    procedure AlertModal(T5CallId : Integer; AlertStr : String);
    procedure Alert(T5CallId : Integer; AlertStr : String; Hwnd : THandle);
    procedure SetWindowToTop;
    property T5CallId : Integer read FT5CallId;
  end;

var
  Frm_alert: TFrm_alert;

implementation

uses u_class_t5connector;

{$R *.dfm}

function TaskBarHeight: integer;

// this is just to get the taskbar height to put the form in the correct position

var hTB: HWND;
    TBRect: TRect;

begin
 hTB := FindWindow('Shell_TrayWnd', ');
 if hTB = 0 then
  Result := 0
 else
  begin
   GetWindowRect(hTB, TBRect);
   if TBRect.Top = 0  // tray bar is positioned to the left or to the right
   then
     Result := 1
   else
    Result := TBRect.Bottom - TBRect.Top;
  end;
end;

function TaskBarWidth: integer;

// this is just to get the taskbar height to put the form in the correct position

var hTB: HWND;
    TBRect: TRect;
begin
 hTB := FindWindow('Shell_TrayWnd', ');
 if hTB = 0 then
  Result := 0
 else
  begin
   GetWindowRect(hTB, TBRect);
   if TBRect.Left = 0  // tray bar is positioned to the left or to the right
    then
     Result := 1
    else
     Result := TBRect.Right - TBRect.Left
  end;
end;

procedure TFrm_alert.SetWindowToTop;
begin
 SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOMOVE);
end;

procedure TFrm_alert.Alert(T5CallId: Integer; AlertStr: String; Hwnd : THandle);
begin
 FT5CallId := T5CallId;
 Lbl_alert.Caption := AlertStr;
 FHwnd := Hwnd;
 ShowWindow(Handle, SW_SHOWNOACTIVATE);
 Visible := True;
end;

procedure TFrm_alert.AlertModal(T5CallId : Integer; AlertStr: String);
begin
 FHwnd := 0;
 FT5CallId := T5CallId;
 Lbl_alert.Caption := AlertStr;
 ShowModal;
end;

procedure TFrm_alert.Button1Click(Sender: TObject);
begin
 Close;
end;

procedure TFrm_alert.CreateParams(var Params: TCreateParams) ;
begin
 inherited;
 with Params do
  begin
   ExStyle := ExStyle or WS_EX_TOPMOST or WS_EX_NOACTIVATE;
   WndParent := GetDesktopwindow;
   Style := Style and not WS_CAPTION;
  end;
end;

procedure TFrm_alert.CreateWindowHandle(const Params: TCreateParams);
begin
 inherited;
 SetWindowToTop;
end;

procedure TFrm_alert.FormClose(Sender: TObject; var Action: TCloseAction);
begin

end;

procedure TFrm_alert.FormCreate(Sender: TObject);
begin
 Left := Screen.Width - TaskBarWidth - Width - 2;
 Top := Screen.Height - Self.Height - TaskBarHeight - 2;
end;

end. 

-----------------------------------------------------
Helping people is my job...

RE: A Mouse Over Form

(OP)
I think that got it, for most part. I guess for the compatibility issue for finding the taskbar, I can search for the window and if it fails, use the SHAppbar routine.

RE: A Mouse Over Form

(OP)

Quote:


I guess for the compatibility issue for finding the taskbar, I can search for the window and if it fails, use the SHAppbar routine.

The FindWindow trick still works in Windows 8.1. Can't believe it, hardly.

RE: A Mouse Over Form

yes I know as this is actual production code (used by over 200 computers ranging from XP to 8.1)

afro

-----------------------------------------------------
Helping people is my job...

RE: A Mouse Over Form

(OP)
Yeah, pre-XP was my problem, if you were wondering. Now I just need to look at the demo I have and see how I want to apply it to these projects here (don't think descending from TForm is going to produce forms that work in the designer - could be wrong though), and make the form stay if the mouse is on it (but that shouldn't be a huge problem).

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members!

Resources

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close