Link to home
Start Free TrialLog in
Avatar of APS NZ
APS NZFlag for New Zealand

asked on

Dropping a menu open from code

Hi

I am beginning to develop an ap using the Microsoft Speech SDK, and I want to use it in command and control mode.  I need to know how to drop open a menu at the top of the screen programmatically.

Thanks in advance for any help

John
Avatar of WiseGuy
WiseGuy

This might help. It lets you simulate mouseclicks

object Form1: TForm1
  Left = 188
  Top = 107
  Width = 260
  Height = 252
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  OnDblClick = FormDblClick
  PixelsPerInch = 96
  TextHeight = 13
  object Label1: TLabel
    Left = 32
    Top = 40
    Width = 7
    Height = 13
    Caption = 'X'
  end
  object Label2: TLabel
    Left = 32
    Top = 96
    Width = 7
    Height = 13
    Caption = 'Y'
  end
  object lblWhereX: TLabel
    Left = 56
    Top = 40
    Width = 6
    Height = 13
    Caption = '?'
  end
  object lblWhereY: TLabel
    Left = 54
    Top = 96
    Width = 6
    Height = 13
    Caption = '?'
  end
  object edtX: TEdit
    Left = 32
    Top = 56
    Width = 121
    Height = 21
    TabOrder = 0
    Text = '369'
  end
  object edtY: TEdit
    Left = 32
    Top = 112
    Width = 121
    Height = 21
    TabOrder = 1
    Text = '220'
  end
  object btnClick: TButton
    Left = 8
    Top = 160
    Width = 75
    Height = 25
    Caption = 'Click'
    TabOrder = 2
    OnClick = btnClickClick
  end
  object btnDblClick: TButton
    Left = 104
    Top = 160
    Width = 75
    Height = 25
    Caption = 'DblClick'
    TabOrder = 3
    OnClick = btnDblClickClick
  end
  object RadioGroup1: TRadioGroup
    Left = 160
    Top = 32
    Width = 89
    Height = 105
    Caption = 'Mouse button'
    ItemIndex = 0
    Items.Strings = (
      'left'
      'right'
      'middle')
    TabOrder = 4
  end
  object Timer1: TTimer
    OnTimer = Timer1Timer
  end
end

unit ufMain;

interface

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

type
  TForm1 = class(TForm)
    edtX: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    edtY: TEdit;
    btnClick: TButton;
    btnDblClick: TButton;
    RadioGroup1: TRadioGroup;
    Timer1: TTimer;
    lblWhereX: TLabel;
    lblWhereY: TLabel;
    procedure btnClickClick(Sender: TObject);
    procedure btnDblClickClick(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure FormDblClick(Sender: TObject);
  private
    { Private declarations }
    procedure WMLButtonDown(var Message: TWMLButtonDown); //message WM_LBUTTONDOWN;
  public
    { Public declarations }
    procedure SimulateDblClick(Msg : Cardinal; X, Y : Cardinal);
    procedure SimulateClick(Msg1, Msg2 : Cardinal; X, Y : Cardinal);
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.btnClickClick(Sender: TObject);
var
  X,Y : Cardinal;
begin
  X := StrToInt(edtX.Text);
  Y := StrToInt(edtY.Text);
  case (self.RadioGroup1.ItemIndex) of
    -1: begin
      exit;
    end; {case-statement}
    0: begin
      // simulate left button click
      SimulateClick(MOUSEEVENTF_LEFTDOWN,MOUSEEVENTF_LEFTUP,X,Y);
    end; {case-statement}
    1: begin
      SimulateClick(MOUSEEVENTF_RIGHTDOWN,MOUSEEVENTF_RIGHTUP,X,Y);
    end; {case-statement}
    2: begin
      SimulateClick(MOUSEEVENTF_MIDDLEDOWN,MOUSEEVENTF_MIDDLEUP,X,Y);
    end; {case-statement}
  end; {case}
end;

procedure TForm1.btnDblClickClick(Sender: TObject);
var
  X,Y : Cardinal;
begin
  X := StrToInt(edtX.Text);
  Y := StrToInt(edtY.Text);
  case (self.RadioGroup1.ItemIndex) of
    -1: begin
      exit;
    end; {case-statement}
    0: begin
      // simulate left button click
      SimulateClick(MOUSEEVENTF_LEFTDOWN,MOUSEEVENTF_LEFTUP,X,Y);
      SimulateClick(MOUSEEVENTF_LEFTDOWN,MOUSEEVENTF_LEFTUP,X,Y);
    end; {case-statement}
    1: begin
      SimulateClick(MOUSEEVENTF_RIGHTDOWN,MOUSEEVENTF_RIGHTUP,X,Y);
      SimulateClick(MOUSEEVENTF_RIGHTDOWN,MOUSEEVENTF_RIGHTUP,X,Y);
    end; {case-statement}
    2: begin
      SimulateClick(MOUSEEVENTF_MIDDLEDOWN,MOUSEEVENTF_MIDDLEUP,X,Y);
      SimulateClick(MOUSEEVENTF_MIDDLEDOWN,MOUSEEVENTF_MIDDLEUP,X,Y);
    end; {case-statement}
  end; {case}
end;

procedure TForm1.SimulateClick(Msg1, Msg2: Cardinal; X, Y: Cardinal);
begin
  SetCursorPos(X,Y);
  mouse_event(MOUSEEVENTF_ABSOLUTE+Msg1,X,Y,0,0);
  mouse_event(MOUSEEVENTF_ABSOLUTE+Msg2,X,Y,0,0);
end;

procedure TForm1.SimulateDblClick(Msg: Cardinal; X, Y: Cardinal);
begin
  SetCursorPos(X,Y);
  mouse_event(MOUSEEVENTF_ABSOLUTE+Msg,X,Y,0,0);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
  aPoint : TPoint;
begin
  GetCursorPos(aPoint);
  lblWhereX.Caption := IntToStr(aPoint.x);
  lblWhereY.Caption := IntToStr(aPoint.y);
end;

procedure TForm1.WMLButtonDown(var Message: TWMLButtonDown);
var
  aMes : TMessage;
begin
  Message.Result := 1;
  aMes := TMessage(Message);
end;

procedure TForm1.FormDblClick(Sender: TObject);
begin
  ShowMessage('DblClick');
end;

end.

WiseGuy, this time you went totally in the wrong direction. The question is about how to show a popup menu and you answered with simulating mouse clicks. Wow! The only bad thing about it, though, is that you proposed an answer...

John, I'd suggest that you look at TrackPoupupMenu(Ex) if you want direct API calls or use TPopupMenu and its method Popup(X, Y).

Ciao, Mike
well you might use this to show the popup menu.

About proposing it as an answer:

I only need a few more points to get into the charts :)

:-))
huh??

you can use a function like this just
add it in your unit ,assign the shortcuts in your menu then call it like:

PostKeyEx32( VK_F1, [ssAlt], false );

{************************************************************
 * Procedure PostKeyEx32
 *
 * Parameters:
 *  key    : virtual keycode of the key to send. For printable
 *           keys this is simply the ANSI code (Ord(character)).
 *  shift  : state of the modifier keys. This is a set, so you
 *           can set several of these keys (shift, control, alt,
 *           mouse buttons) in tandem. The TShiftState type is
 *           declared in the Classes Unit.
 *  specialkey: normally this should be False. Set it to True to
 *           specify a key on the numeric keypad, for example.
 * Description:
 *  Uses keybd_event to manufacture a series of key events matching
 *  the passed parameters. The events go to the control with focus.
 *  Note that for characters key is always the upper-case version of
 *  the character. Sending without any modifier keys will result in
 *  a lower-case character, sending it with [ssShift] will result
 *  in an upper-case character!
 *Created: 17.7.98 by P. Below
 ************************************************************}
Procedure PostKeyEx32( key: Word; Const shift: TShiftState;
                     specialkey: Boolean );
  Type
    TShiftKeyInfo = Record
                      shift: Byte;
                      vkey : Byte;
                    End;
    byteset = Set of 0..7;
  Const
    shiftkeys: Array [1..3] of TShiftKeyInfo =
      ((shift: Ord(ssCtrl); vkey: VK_CONTROL ),
       (shift: Ord(ssShift); vkey: VK_SHIFT ),
       (shift: Ord(ssAlt); vkey: VK_MENU ));
  Var
    flag: DWORD;
    bShift: ByteSet absolute shift;
    i: Integer;
  Begin
    For i := 1 To 3 Do Begin
      If shiftkeys[i].shift In bShift Then
        keybd_event( shiftkeys[i].vkey,
                     MapVirtualKey(shiftkeys[i].vkey, 0),
                     0, 0);
    End; { For }
    If specialkey Then
      flag := KEYEVENTF_EXTENDEDKEY
    Else
      flag := 0;

    keybd_event( key, MapvirtualKey( key, 0 ), flag, 0 );
    flag := flag or KEYEVENTF_KEYUP;
    keybd_event( key, MapvirtualKey( key, 0 ), flag, 0 );

    For i := 3 DownTo 1 Do Begin
      If shiftkeys[i].shift In bShift Then
        keybd_event( shiftkeys[i].vkey,
                     MapVirtualKey(shiftkeys[i].vkey, 0),
                     KEYEVENTF_KEYUP, 0);
    End; { For }
  End; { PostKeyEx32 }

Regards Barry
Avatar of APS NZ

ASKER

Hi WiseGuy, Mike and Barry - thanks for the replies. I did not realise it was such a complex issue.

Barry, your answer is what I need, so if you would like to turn it into an answer I will give you the points and add an extra 50 for the complexity of the answer.

Thanks again guys

John

ASKER CERTIFIED SOLUTION
Avatar of inthe
inthe

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Barry, John,

please help me. I don't see any relevance of Barry's answer regarding the question. As it is said that it is the solution I must be missing some important point here. John, you said you want:

"...open a menu at the top of the screen programmatically."

But Barry gave you a solution to generate key events. What has this to do with showing a popup?

Ciao, Mike
i assume it is a Tmainmenu and if you set the menus keyboard shortcuts well the rest is done by the postkeyex()
function...

for instance first menuitem is "file" with keyboard shortcut of "alt - f1" the using PostKeyEx32( VK_F1, [ssAlt], false ); will drop the menu as per question..

Aah, thank you Barry. Now I understand. The question is to issue the key commands programmatically to open a menu and select a specific entry. I always assumend it was about showing a TMenu :-)

Ciao, Mike
Avatar of APS NZ

ASKER

Adjusted points to 100
Avatar of APS NZ

ASKER

Mike

The way Barry describes it is the way I wanted to do it, and of course it works!

John
Mmmh, what I wonder is why nobody, in particular you John, has corrected me? So I was totally wrong here and charged WiseGuy being wrong (sorry WiseGuy!).

Ciao, Mike