PopupMenu der popper "opad" (bogstavligt)

Tags:    delphi

Jeg har en TSpeedButton (sbtnStatus) og en TPopupMenu (pmStatus) med nogle MenuItems.

I sbtnStatus' OnClick-event har jeg følgende kode:
procedure TForm1.sbtnStatusClick(Sender: TObject);
var
PopupPos: TPoint;
begin
PopupPos := sbtnStatus.ClientToScreen(Point(sbtnStatus.Left, sbtnStatus.Top + sbtnStatus.Height));
pmStatus.Popup(PopupPos.X, PopupPos.Y);
end;

Det virker fint, Popup-menuen popper op når man kliker på sbtnStatus. Den kommer frem nedenfor sbtnStatus, den popper altså "nedad".

Nu vil jeg gerne have den til at poppe "opad", så den kommer ovenfor sbtnStatus.
Jeg vil prøve at "tegne" hvad jeg mener:
______________
| Item1 |
| Item2 |
| Item3 |
|_____________|___
| sbtnStatus |
|________________|

Hvordan gør man det?

Jeg ved det er muligt, for IM-programmet Miranda IM (www.miranda-im.org), der er et Win32-opensource-program skrevet i C, har den funktion i sin statusbar (også når man gør Miranda IM's vindue lille, og flytter det op i toppen af skærmen, så det er ingen forklaring)...

Jeg bruger Delphi 7 Personal under Windows XP.

På forhånd tak :-)



3 svar postet i denne tråd vises herunder
1 indlæg har modtaget i alt 1 karma
Sorter efter stemmer Sorter efter dato
Jeg har en TSpeedButton (sbtnStatus) og en TPopupMenu (pmStatus) med nogle MenuItems.

I sbtnStatus' OnClick-event har jeg følgende kode:
procedure TForm1.sbtnStatusClick(Sender: TObject);
var
PopupPos: TPoint;
begin
PopupPos := sbtnStatus.ClientToScreen(Point(sbtnStatus.Left, sbtnStatus.Top + sbtnStatus.Height));
pmStatus.Popup(PopupPos.X, PopupPos.Y);
end;

Det virker fint, Popup-menuen popper op når man kliker på sbtnStatus. Den kommer frem nedenfor sbtnStatus, den popper altså "nedad".

Nu vil jeg gerne have den til at poppe "opad", så den kommer ovenfor sbtnStatus.
Jeg vil prøve at "tegne" hvad jeg mener:
______________
| Item1 |
| Item2 |
| Item3 |
|_____________|___
| sbtnStatus |
|________________|

Hvordan gør man det?

Jeg ved det er muligt, for IM-programmet Miranda IM (www.miranda-im.org), der er et Win32-opensource-program skrevet i C, har den funktion i sin statusbar (også når man gør Miranda IM's vindue lille, og flytter det op i toppen af skærmen, så det er ingen forklaring)...

Jeg bruger Delphi 7 Personal under Windows XP.

På forhånd tak :-)


Det her skulle virke:

procedure TForm1.sbtnStatusClick(Sender: TObject);
var
PopupPos: TPoint;
begin
PopupPos := ClientToScreen(Point(sbtnStatus.Left, sbtnStatus.Top + sbtnStatus.Height));
pmStatus.Popup(PopupPos.X, PopupPos.Y - (pmStatus.Items.Count * 17 + 6 + sbtnStatus.Height));
end;

Jeg tror ikke at man kan få den til at hoppe opad med skygge osv.

Emil Melgaard
- Admin på gruppen Delphi spilprogrammering.
http://www.delphispilprogram.udvikleren.dk

[Redigeret d. 02/11-03 02:28:12 af Emil Melgaard]



Jeg har en TSpeedButton (sbtnStatus) og en TPopupMenu (pmStatus) med nogle MenuItems.

I sbtnStatus' OnClick-event har jeg følgende kode:
procedure TForm1.sbtnStatusClick(Sender: TObject);
var
PopupPos: TPoint;
begin
PopupPos := sbtnStatus.ClientToScreen(Point(sbtnStatus.Left, sbtnStatus.Top + sbtnStatus.Height));
pmStatus.Popup(PopupPos.X, PopupPos.Y);
end;

Det virker fint, Popup-menuen popper op når man kliker på sbtnStatus. Den kommer frem nedenfor sbtnStatus, den popper altså "nedad".

Nu vil jeg gerne have den til at poppe "opad", så den kommer ovenfor sbtnStatus.
Jeg vil prøve at "tegne" hvad jeg mener:
______________
| Item1 |
| Item2 |
| Item3 |
|_____________|___
| sbtnStatus |
|________________|

Hvordan gør man det?

Jeg ved det er muligt, for IM-programmet Miranda IM (www.miranda-im.org), der er et Win32-opensource-program skrevet i C, har den funktion i sin statusbar (også når man gør Miranda IM's vindue lille, og flytter det op i toppen af skærmen, så det er ingen forklaring)...

Jeg bruger Delphi 7 Personal under Windows XP.

På forhånd tak :-)

Det her skulle virke:

procedure TForm1.sbtnStatusClick(Sender: TObject);
var
PopupPos: TPoint;
begin
PopupPos := ClientToScreen(Point(sbtnStatus.Left, sbtnStatus.Top + sbtnStatus.Height));
pmStatus.Popup(PopupPos.X, PopupPos.Y - (pmStatus.Items.Count * 17 + 6 + sbtnStatus.Height));
end;

Jeg tror ikke at man kan få den til at hoppe opad med skygge osv.

Emil Melgaard
- Admin på gruppen Delphi spilprogrammering.
http://www.delphispilprogram.udvikleren.dk

[Redigeret d. 02/11-03 02:28:12 af Emil Melgaard]


PopupPos := sbtnStatus.ClientToScreen(Point(sbtnStatus.Left, sbtnStatus.Top + sbtnStatus.Height));
pmStatus.Popup(PopupPos.X, PopupPos.Y - (pmStatus.Items.Count * 17 + 6 + sbtnStatus.Height));

Hvordan kan man sikre sig, at MenuItem'sne altid har samme højde (17 pixels)?
Det tror jeg nemlig ikke altid er tilfældet... Det kan være, den enkelte bruger har valgt en anden skrifttype, eller måske et andet WinXP-theme...




Jeg har nu fundet en løsning via Windows API, der gør det jeg vil, på http://www.delphi3000.com/articles/article_3647.asp
Da artiklen ikke bare kan læses, men kræver at man registrerer sig (selv da kan man kun læse op til 50 gratis artikler), er her den kode jeg er nået frem til:

type
TForm1 = class(TForm)
sbtnStatus: TSpeedButton;
procedure sbtnStatusClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
protected
procedure WMCommand(var Msg: TWMCommand); message WM_COMMAND;
public
pmStatus: TPopUpMenu;
end;

const
WM_STATUSOFFLINE = WM_USER + 101;
WM_STATUSONLINE = WM_USER + 102;

implementation

{$R *.dfm}

procedure TForm1.WMCommand(var Msg: TWMCommand);
begin
case Msg.ItemID of
WM_STATUSOFFLINE:
sbtnStatus.Caption := 'Offline';
WM_STATUSONLINE:
sbtnStatus.Caption := 'Online';
end;

inherited;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
IndlaegRec: TIndlaegNoteRec;
begin
pmStatus := TPopUpMenu.Create(Self);

pmStatus.AutoPopup := FALSE;
pmStatus.AutoHotkeys := maManual;

AppendMenu(pmStatus.Handle, MF_STRING or MF_UNCHECKED, WM_STATUSOFFLINE, '&Offline');
AppendMenu(pmStatus.Handle, MF_STRING or MF_UNCHECKED, WM_STATUSONLINE, '&Online');
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
pmStatus.Free;
end;

procedure TForm1.sbtnStatusClick(Sender: TObject);
var
Msg : LongBool;
PopupPos: TPoint;
begin
PopupPos := sbtnStatus.ClientToScreen(Point(sbtnStatus.Left, sbtnStatus.Top));
Msg := TrackPopupMenuEx(pmStatus.Handle, TPM_LEFTALIGN or TPM_LEFTBUTTON or TPM_BOTTOMALIGN or TPM_RETURNCMD, PopupPos.X, PopupPos.Y, Handle, nil);
if Msg then
SendMessage(Handle, WM_COMMAND, Integer(Msg), 0);
end;



t