Solved

Pretty damn hard...

Posted on 2002-06-11
16
200 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
Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
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
 
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

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Suggested Solutions

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
In an interesting question (https://www.experts-exchange.com/questions/29008360/) here at Experts Exchange, a member asked how to split a single image into multiple images. The primary usage for this is to place many photographs on a flatbed scanner…

828 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