Creating a menu button in Windows - windows

Microsoft's User Experience Interaction Guidelines give some UI guidelines for when to use a menu button:
http://i.msdn.microsoft.com/Aa511453.command51(en-us,MSDN.10).png
How do I create one of these menu buttons? I've found information on
how to create a split button in Vista and above
how to create a toolbar button with a dropdown menu
how to create a regular pushbutton and manually wire up an OnClick event handler that pops up a menu
But is there any standard way to create a button, not in a toolbar, with the little down triangle, that automatically pops up a menu when clicked?
(I'm using Delphi / C++Builder, but other solutions are welcome.)

You can use the OnClick to force the popup, and for consistency don't use the cursor position, but rather the control position.
procedure TForm1.Button1Click(Sender: TObject);
var
pt : TPoint;
begin
Pt.X := Button1.Left;
Pt.Y := Button1.Top+Button1.Height;
pt := ClientToScreen(Pt);
PopupMenu1.Popup(pt.x,pt.y);
end;
You can then add the "glyph" using either a Delphi 2010 button, or a previous version TBitBtn and assign the bitmap/glyph property to an appropriate image and align right.

You don't mention which version of Delphi you are using, but in Delphi 2010 TButton has new properties for this: DropDownList which can be associated with a TPopupMenu to define the menu items, and Style which can be set to bsSplitButton.
This produces a button that you can press that also has a dropdown arrow on the right of it, To make the menu popup when you click to the left of the arrow this code in the button click handler should do the job.
procedure TForm1.Button1Click(Sender: TObject);
var
CursorPos: TPoint;
begin
GetCursorPos(CursorPos);
PopupMenu1.Popup(CursorPos.X, CursorPos.Y);
end;
in previous versions of Delphi I think you had to use TToolBar.

Related

Hiding Taskbar Button works, but not when second form is shown [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I managed to hide my winforms application taskbar button using
ShowWindow(GetParent(Form1.Handle),SW_HIDE);
This i call on timer 1 second after the form is created. The taskbar button remain hidden through out the application usage, but until I click a button on the form to show another form, with the Form1 as the owner.
I try to use the same code to hide the second form but not able to work.
Edit: Adding more codes:
Codes in Form1:
// this fires every 1 second and works well.
procedure TForm1.scanTimerTimer(Sender: TObject);
begin
ShowWindow(GetParent(Form1.Handle),SW_HIDE);
end;
// when a user press Settings button on the Form1
// I open another form.
procedure TForm1.SettingsBtnClick(Sender: TObject);
var
settings: TSettingsForm;
begin
settings := TSettingsForm.Create(Form1);
settings.Show;
end;
Codes in SettingsForm
// this fires every 1 second and DOESNT WORK!
procedure TSettingsForm.scanTimerTimer(Sender: TObject);
begin
ShowWindow(GetParent(SettingsForm.Handle),SW_HIDE);
end;
That's all there is for the codes. So when I open SettingsForm, immediately the taskbar button reappears and never disappears anymore. I want taskbar to remain hidden no matter how many other forms I open from the main form.
I tried a "OS specific API" for windows which is
ShowWindow(GetParent(Form1.Handle),SW_HIDE);
Which works after FormCreate, but after the main window opens a secondary window,
the taskbar button reappears. So if your app just have one window, you can use this. But for multiple windows/forms app, it will not work!
Also I tried Non OS Specific API:
SettingsForm.ShowInTaskBar := stNever;
Tried putting this in FormCreate, and also just before Show in Caller form, but still it doesn't work. The taskbar button still appears.
Finally I found in lazarus forum the answer using a OS Specific API:
You need to add 2 imports:
InterfaceBase, Win32Int
And put this is FormCreate:
procedure TForm1.FormCreate(Sender: TObject);
var
i: integer;
EXStyle: Long;
AppHandle: THandle;
begin
AppHandle := TWin32WidgetSet(WidgetSet).AppHandle;
EXStyle:= GetWindowLong(AppHandle, GWL_EXSTYLE);
SetWindowLong(AppHandle, GWL_EXSTYLE, EXStyle or WS_EX_TOOLWINDOW and not WS_EX_APPWINDOW);
end;

show a popup menu when I left click on a button in oracle form

I have created a popup menu and assigned it into a button,when i right click
the button the popup menu will be displayed.Now i want if i normally click the
button that is left click the popup menu to be displayed
It works in Oracle Forms 6:
declare
w_id pls_integer;
begin
w_id := GET_ITEM_PROPERTY(Find_Item('CONTROL.B_REPORTS'), WINDOW_HANDLE);
WIN_API_SHELL.SendMessage( w_id, 516 ); -- WM_RBUTTONDOWN
WIN_API_SHELL.SendMessage( w_id, 517 ); -- WM_RBUTTONUP
end;
I completely agree with #APC above; this is not a standard UI convention. And it is not possible to override the default functionality of the right click menu within Forms. You could however, build a small window/canvas/block made to look like the right click menu and default it's starting window position to be the mouse X,Y coordinate.

How to pass keystrokes onto a second active form in Firemonkey

I encountered some behavior in FMX that is different in VCL. This relates to how main menu shortcuts are processed. It seems that an FMX application will intercept all shortcut keystrokes in the main form such that any other active forms do not see these keystrokes.
This means for example if you have a TMemo on a second form and the main form uses the Ctrl-V main menu short cut, it's not possible to paste text into the memo using Ctrl-V. This is unique to FMX, VCL works as expected where a second form receives all keystrokes irrespective of shortcuts on a main form.
An answer in this question How to intercept Menu shortcut event in Firemonkey explains how to intercept shortcuts in the main form.
The question here is how to get these intercepted keystrokes from the main form to the currently active form, so that controls such as TMemo or TEdit on the second form work as expected?
Based on the answer in How to intercept Menu shortcut event in Firemonkey, one way to pass on the mainmenu shortcut keystrokes, eg Ctrl-A, to the currently active form is to use this code in the main form:
TMenuItem = class(FMX.Menus.TMenuItem)
protected
procedure DialogKey(var Key: Word; Shift: TShiftState); override;
end;
procedure TMenuItem.DialogKey(var Key: Word; Shift: TShiftState);
var ch : char;
begin
if (ssCtrl in Shift) and (Key = 65){A} then
begin
ch := #0;
Screen.ActiveForm.KeyDown(Key, ch, Shift);
exit;
end;
inherited;
end;
An alternative answer to the first one, it's works but not everyone might like it, plus it has limitations. For simple cases is should work.
Before showing the second form, remove the shortcuts from the mainform, then restore the shortcuts when the form returns control to the mainform. Works ok if the second form is shown using showmodal. Pity there isn't a form OnShortCut event as we have in VCL. Eg rough example:
(MainMenu.Items[0] as TMenuItem).Items[0].ShortCut := TextToShortCut('');
FormTwo.ShowModal;
(MainMenu.Items[0] as TMenuItem).Items[0].ShortCut := TextToShortCut('Ctrl+V');

How do I put a form in to help mode?

I am trying to put form into "help mode" in Delphi 2010.
I have a button which the user clicks, and I want the cursor to change to the help cursor, then when a user clicks onto a control, the help for the control is displayed
Is there a window message that I can send?
Send a WM_SYSCOMMAND message to the form passing SC_CONTEXTHELP as lParam.
Changes the cursor to a question mark with a pointer. If the user then clicks a control in the dialog box, the control receives a WM_HELP message.
Write something like this in your button OnClick event handler:
procedure TMyForm.Button1Click(Sender: TObject);
begin
SendMessage(Handle, WM_SYSCOMMAND, SC_CONTEXTHELP, 0);
end;

How can I get taskbar buttons for forms that aren't the main form?

How do you make a form appear on the taskbar in Delphi? In Firefox, for example, when you open a page in a new window, it creates another window on the taskbar without creating a new process. At the moment my Delphi application opens a new form when a button is clicked, but there is still only one thing on the task bar, so you can't alt-tab between the main form and the form that is created when the button is clicked. How do I change it so that the new form appears with a new taskbar button? My current code looks like this:
procedure Form1ButtonClick(Sender: TObject);
begin
Form2.Show;
end;
I have been messing around with CreateWindowEx, but ideally I would like to find a simpler solution than directly using the Windows API.
If I understand what you want correctly, you can show your secondary forms on the task bar by overriding it's CreateParams procedure, as explained in Minimize child forms independent of the main form delphi.about.com article, like this:
interface
type
TMyForm = class(TForm)
...
protected
procedure CreateParams(var Params: TCreateParams) ; override;
...
implementation
procedure TMyForm.CreateParams(var Params: TCreateParams) ;
begin
inherited;
Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
Params.WndParent := 0;
end;
if not using of this line is better in form order :
Params.WndParent := 0;

Resources