Solved

Pretty damn hard...

Posted on 2002-06-11
16
198 Views
Last Modified: 2010-04-04
How can i handle other applications SystemMenu's ?

I'm writing a Taskbar replacement application to be run in a Citrix Environment...but that's not really the point.

I know how to get the SystemMenu's...but i can't seem to get those SystemMenu's to Work with TrackPopupMenu...what can i do ?

Does the process need to have any special priveleges to handle other applications systemmenu's ?

Will Inc(Points, ManyMore); for a nice answer. =)

Regards
//raidos

0
Comment
Question by:raidos
  • 8
  • 7
16 Comments
 
LVL 12

Expert Comment

by:Lee_Nover
ID: 7071166
also interested ;)
0
 
LVL 14

Expert Comment

by:DragonSlayer
ID: 7071765
If you want to modify/access other applications system menu, you would need to create a DLL to do so and then inject that DLL into the application.

Madshi should be the right person to point you to the right direction in this :)
0
 
LVL 14

Expert Comment

by:DragonSlayer
ID: 7071770
Or you could just use his (Madshi's) components to do so... check out his page at http://www.madshi.net, click on Delphi, then click on madCodeHook.

Docs are available here as well: http://help.madshi.net/Data/madCodeHook.htm


HTH
DragonSlayer
0
 
LVL 3

Author Comment

by:raidos
ID: 7072182
ohh...well....
i've got to disagree that injecting is necessary....
i can remove/disable any menuitem on any process SystemMenu straight from my application.

I don't see why i shouldn't be able to use TrackPopupMenu directly from my application with the SystemMenu that it uses...

Hoping for a different solution...

Regards
//raidos
0
 
LVL 14

Expert Comment

by:DragonSlayer
ID: 7072199
Yes you can add/remove menuitems... that's because you can get the handle to the system menus. But if you want to do other things (such as adding a new menuitem and executing a command when user clicks on the menuitem), then you need to inject your DLL into the process.
0
 
LVL 3

Author Comment

by:raidos
ID: 7072204
I don't want to add new menuitems i just want to handle the menuitems that are already inside the SystemMenu...

just the way the "Explorer" taskbar does it.

And adding new menuitems is possible without injecting a dll, a SystemHook would be possible to use too...unless i'm missing something...

Regards
//raidos
0
 
LVL 3

Author Comment

by:raidos
ID: 7072408
I've managed to move on a bit...

but with applications that are not created with borland tools it seems i get an error, 1401 := "Invalid menu" don't know why...the Var I use contains the "Correct SystemMenu"

This is the code i use:
  Window := FindWindow(Nil, 'Delphi 5'); //Change 'Delphi 5' to whatever application..
  SysMenu := GetSystemMenu(Window, FALSE);

  DrawMenuBar(Window);

  I := LongInt(TrackPopupMenu(SysMenu, TPM_CENTERALIGN OR TPM_LEFTBUTTON OR TPM_RETURNCMD, Mouse.CursorPos.X, Mouse.CursorPos.y, 0, Form1.Handle, Nil));
  If I <> 0 Then
    PostMessage(Window, WM_SYSCOMMAND, I,0)
  Else begin
    I := GetLastError;
    ShowMessage(IntToStr(I));
  End;

Regards
//raidos
0
 
LVL 14

Expert Comment

by:DragonSlayer
ID: 7072442
Here's mine:

unit uMain;

interface

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

type
  TForm1 = class(TForm)
    ListBox1: TListBox;
    Panel1: TPanel;
    Panel2: TPanel;
    Button1: TButton;
    Label1: TLabel;
    Label2: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure ListBox1Click(Sender: TObject);
    procedure Panel1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

function EnumWindowsProc(AHandle: HWND; Param: LPARAM): BOOL; export; stdcall;
var
  WinText: array [0 .. 4096] of Char;
  ACap: string;
begin
  Result := True;
  GetWindowText(AHandle, @WinText[0], 4096);
  ACap := WinText;
  SetLength(ACap, StrLen(WinText));
  if (ACap <> '') and (IsWindowVisible(AHandle)) then
    Form1.ListBox1.Items.AddObject(WinText, TObject(AHandle));
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ListBox1.Clear;
  EnumWindows(@EnumWindowsProc, 0);
end;

procedure TForm1.ListBox1Click(Sender: TObject);
var
  SysMenuHandle: THandle;
  AppHandle: THandle;
  PopupMenu: TPopupMenu;
begin
  if ListBox1.ItemIndex > -1 then
  begin
    AppHandle := Integer(ListBox1.Items.Objects[ListBox1.ItemIndex]);
    Label1.Caption := ListBox1.Items[ListBox1.ItemIndex] +
      ' @ $' + IntToHex(AppHandle, 8);
  end else Label1.Caption := 'Nothing Selected';
end;

procedure TForm1.Panel1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  ScreenPoint: TPoint;
  SysMenuHandle: THandle;
  AppHandle: THandle;
begin
  if not (Button = mbRight) then
    Exit;
  if ListBox1.ItemIndex = -1 then
    Exit;

  AppHandle := Integer(ListBox1.Items.Objects[ListBox1.ItemIndex]);
  ScreenPoint := Panel1.ClientToScreen(Point(X, Y));
  SysMenuHandle := GetSystemMenu(AppHandle, False);
  TrackPopupMenu(SysMenuHandle,
    TPM_CENTERALIGN or TPM_LEFTBUTTON or TPM_RETURNCMD,
    ScreenPoint.x, ScreenPoint.y, 0, Handle, nil);
  PostMessage(AppHandle, WM_SYSCOMMAND, 1, 0);
end;

end.
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 14

Expert Comment

by:DragonSlayer
ID: 7072444
And the form:


object Form1: TForm1
  Left = 192
  Top = 106
  Width = 518
  Height = 443
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object ListBox1: TListBox
    Left = 0
    Top = 41
    Width = 510
    Height = 334
    Align = alClient
    ItemHeight = 13
    TabOrder = 0
    OnClick = ListBox1Click
  end
  object Panel1: TPanel
    Left = 0
    Top = 375
    Width = 510
    Height = 41
    Align = alBottom
    Caption = 'Click Area'
    TabOrder = 1
    OnMouseUp = Panel1MouseUp
    object Label2: TLabel
      Left = 8
      Top = 16
      Width = 32
      Height = 13
      Caption = 'Label2'
    end
  end
  object Panel2: TPanel
    Left = 0
    Top = 0
    Width = 510
    Height = 41
    Align = alTop
    TabOrder = 2
    object Label1: TLabel
      Left = 90
      Top = 13
      Width = 82
      Height = 13
      Caption = 'Nothing Selected'
    end
    object Button1: TButton
      Left = 5
      Top = 8
      Width = 75
      Height = 25
      Caption = 'Refresh'
      TabOrder = 0
      OnClick = Button1Click
    end
  end
end




The menus came out, but they are not functional. Also, for Delphi apps, you will find two windows for each app, because of the use of TApplication (check out the programme and you will see)


HTH
DragonSlayer
0
 
LVL 3

Author Comment

by:raidos
ID: 7072497
Nice little Application, but it doesn't do anything i haven't already tried, sadly...

and the popupmenus seem to only work with Applications written with Delphi/C++ Builder/* Borland * ?

Will work on my function a bit more, perhaps i need to get the MainFormHandle for the window or something...

Regards
//raidos
0
 
LVL 3

Author Comment

by:raidos
ID: 7074182
I've gotten it to work now, it's wierd though it only works if the applications are started after the my little "Taskbar" replacement...

so if i start IE before it is unable to Handle IE's SystemMenu, but if IE is started after my little proggy it works like a charm...seriously wierd...

any ideas on that ?

Points will to be delivered to you soon DragonSlayer

Regards
//raidos
0
 
LVL 14

Expert Comment

by:DragonSlayer
ID: 7074422
> it's wierd though it only works if the applications are started after the my little "Taskbar" replacement...

What works? You mean you will only be able to get the menu if the applications are started after yours? Or did you mean that the menu becomes functional if the apps are started after yours?



DragonSlayer
0
 
LVL 3

Author Comment

by:raidos
ID: 7074773
Dragonslayer, I only get the menu for the application if it was started after mine...

//raidos
0
 
LVL 14

Accepted Solution

by:
DragonSlayer earned 100 total points
ID: 7074783
Hmm... the sample I posted above works all the time. Tested in Win2K and Win98SE
0
 
LVL 3

Author Comment

by:raidos
ID: 7074881
Your sample doesn't work "all the time" for me....sadly...but it doesn't matter anyhow, im going to start my "taskbar" replacement before any other apps anyway...

Regards
//raidos
0
 
LVL 14

Expert Comment

by:DragonSlayer
ID: 7074946
please feel free to ask... I might not have all the answers, but we can surely discuss and explore ;)
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Activex get website that activex running on 3 85
Simple Delphi Question 9 83
How to debug For loops? 3 46
tvirtualstringtree freeze when load too manny images 10 53
A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Hi friends,  in this video  I'll show you how new windows 10 user can learn the using of windows 10. Thank you.
Many functions in Excel can make decisions. The most simple of these is the IF function: it returns a value depending on whether a condition you describe is true or false. Once you get the hang of using the IF function, you will find it easier to us…

863 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

24 Experts available now in Live!

Get 1:1 Help Now