Can we create a multicolumn menu in Lazarus? lazarus / 39-Graphics ---------------------------------------------------------------------- vkhoa · 2015-10-08 07:50 for example like the choose color menu in Word I want a grid menu which is used to choose a list of special characters ---------------------------------------------------------------------- zeljko · 2015-10-08 09:34 I don't think it's possible, but you can create your own popup form and put whatever you want inside that form ... ---------------------------------------------------------------------- rvk · 2015-10-08 09:48 Quote from: vkhoa on October 08, 2015, 09:50:58 amfor example like the choose color menu in Word I want a grid menu which is used to choose a list of special characters What exactly are you after? Something like the "Character map" (Lazarus > Edit > Insert from Character Map) ? ---------------------------------------------------------------------- Graeme · 2015-10-08 11:13 Quote from: vkhoa on October 08, 2015, 09:50:58 amfor example like the choose color menu in Word I want a grid menu which is used to choose a list of special characters Not possible with LCL as far as I know, but is possible with custom drawn toolkits like fpGUI. As a work-around, you could do what fpGUI does as standard (in any text input widgets) - add a popup menu with a "Insert from Character Map" menu entry. ---------------------------------------------------------------------- vkhoa · 2015-10-09 06:20 Thanks all for the quick replies. @zeljko, @Graeme I see. @rvk Yes, it likes characters maps, but it is the menu of my application ---------------------------------------------------------------------- rvk · 2015-10-09 09:10 Quote from: vkhoa on October 09, 2015, 08:20:04 amYes, it likes characters maps, but it is the menu of my application Do you mean something like attached image? (If not you might want to sketch something as how you want it and post it. Images/sketches are much clearer than words) You could create a normal TMainMenu and on the MenuItems.OnClick you could open a separate form (with ShowModal) containing a StringGrid with all your options. That form can be created on the fly (in code) and if done right, it could act just like a submenu with columns. Unfortunately there is no component (that I know of) that does this already. ---------------------------------------------------------------------- rvk · 2015-10-09 09:48 Okay (I couldn't leave it alone ). I didn't find an option in Lazarus to set MF_MENUBREAK to make a TMenuItem go to a new column. In Delphi this is much easier (just set TMenuItem.Break to mbBreak). But if you're on Windows you could do it (with some hackery ) Use the following function (which I took from lcl\interfaces\win32win32wsmenus.pp): Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i uses Windows, function myChangeMenuFlag(const AMenuItem: TMenuItem; Flag: Cardinal; Value: boolean): boolean;var  MenuInfo: MENUITEMINFO;     // TMenuItemInfoA and TMenuItemInfoW have same size and same structure typebegin  FillChar(MenuInfo, SizeOf(MenuInfo), 0);  MenuInfo.cbSize := sizeof(TMenuItemInfo);  MenuInfo.fMask := MIIM_FTYPE;         // don't retrieve caption (MIIM_STRING not included)  GetMenuItemInfo(AMenuItem.Parent.Handle, AMenuItem.Command, False, @MenuInfo);  if Value then    MenuInfo.fType := MenuInfo.fType or Flag  else    MenuInfo.fType := MenuInfo.fType and (not Flag);  Result := SetMenuItemInfo(AMenuItem.Parent.Handle, AMenuItem.Command, False, @MenuInfo);  //TriggerFormUpdate(AMenuItem);end; Now create a large menu with lots of MenuItems. Determine where you want to go to a new column and use the following command in FormCreate() (for instance for MenuItem5): Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   myChangeMenuFlag(MenuItem5, MF_MENUBREAK, true); Now, when you run your program, you have a MainMenu with columns ---------------------------------------------------------------------- Graeme · 2015-10-09 10:09 Quote from: rvk on October 09, 2015, 11:10:39 amUnfortunately there is no component (that I know of) that does this already. Sadly, this was supported natively by OS/2 2.11 already back in 1990. Attached is a scanned image from a book I have Real-World Programming for OS/2 2.11. From quickly scanning through the Menus chapter, it looks like multi-column popup menus under OS/2 is achieved by defining your menus with the MIS_STATIC, MIA_FRAMED and MIS_BREAKSEPARATOR menu attributes. The latter is what causes a multi-column menu to appear. Windows was heavily influenced by OS/2, so Windows might still have similar menu attributes. Obviously that would only work for LCL-Win32 with direct Win32 API calls, and not for any other OS targets. ---------------------------------------------------------------------- rvk · 2015-10-09 10:12 Quote from: Graeme on October 09, 2015, 12:09:21 pmQuote from: rvk on October 09, 2015, 11:10:39 amUnfortunately there is no component (that I know of) that does this already. Sadly, this was supported natively by OS/2 2.11 already back in 1990. Attached is a scanned image from a book I have Real-World Programming for OS/2 2.11. From quickly scanning through the Menus chapter, it looks like multi-column popup menus under OS/2 is achieved by defining your munes with the MIS_STATIC, MIA_FRAMED and MIS_BREAKSEPARATOR menu attributes. Windows was heavily influenced by OS/2, so Windows might still have similar menu attributes. Obviously that would only work for LCL-Win32, and not for any other OS targets. I already posted a function to achieve similar under Windows. It's done by setting the MF_MENUBREAK flag on a TMenuItem. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   myChangeMenuFlag(MenuItem5, MF_MENUBREAK, true);  myChangeMenuFlag(MenuItem8, MF_MENUBREAK, true); ---------------------------------------------------------------------- vkhoa · 2015-10-10 06:24 Thanks! I'll try it later I have posted the screenshot which is what I wanted, but instead of the color square, I will draw a symbol or an image at each square. Is it posible? I also want to change the square size. ---------------------------------------------------------------------- rvk · 2015-10-10 08:59 Quote from: vkhoa on October 10, 2015, 08:24:49 amI have posted the screenshot which is what I wanted, but instead of the color square, I will draw a symbol or an image at each square. Is it posible? I also want to change the square size. You could draw images in a menu but you don't have much control over the rest of the appearance. So if you want to do what you described, it's best to go with a separate form which you can popup. Do the squares need to be of different size of are they all the same size? If they all are the same size you could create a form with TDrawGrid and you can draw the images on that. If the squares are of different sizes you could just but several TSpeedButtons or TBitBtns on the form. That's why a real sketch of your interface is important, so you know where you're working towards. Also the functionality needs to be described. Do you need to select an options with your keyboard or is clicking an image enough? ---------------------------------------------------------------------- wp · 2015-10-11 22:09 vkhoa, the attached demo maybe gets close to what you want. It creates a form as suggested by rvk onto which a series of speedbuttons are placed, each one with its assigned color. This form can be opend from a toolbutton. A question to the experts: This pseudo popup-menu inherits from a form, and therefore it looks differently from the regular PopupMenus. Is there a way to "hijack" the window opened by a TPopupMenu component and place the buttons into it? A second question: In the Office applications the color selection toolbuttons are usually split: a dropdown button to show the popup menu, and a regular toolbutton the apply the previously selected color. Is there a way to distinguish that a mouse click occured on the arrow or button part of a TToolbutton with style tbsDropdown? ---------------------------------------------------------------------- rvk · 2015-10-12 10:57 Quote from: wp on October 12, 2015, 12:09:03 amvkhoa, the attached demo maybe gets close to what you want. It creates a form as suggested by rvk onto which a series of speedbuttons are placed, each one with its assigned color. This form can be opend from a toolbutton.Nice little demo  (This would make a nice alternative ColorPicker. The TColorDialog is always a separate dialog but this is much nicer) Quote from: wp on October 12, 2015, 12:09:03 amA question to the experts: This pseudo popup-menu inherits from a form, and therefore it looks differently from the regular PopupMenus. Is there a way to "hijack" the window opened by a TPopupMenu component and place the buttons into it?As TPopupMenu inherits from TMenu and that in turn uses the Windows-api to draw the menus I don't think it's possible to "hijack" that window. But what do you see different from the regular PopupMenus about this? I think it really looks good. I don't think Word uses TMenu for this either. The only thing might be that Word could be using a TPanel instead of a TForm to show this but I'm not sure. Quote from: wp on October 12, 2015, 12:09:03 amA second question: In the Office applications the color selection toolbuttons are usually split: a dropdown button to show the popup menu, and a regular toolbutton the apply the previously selected color. Is there a way to distinguish that a mouse click occured on the arrow or button part of a TToolbutton with style tbsDropdown? Yeah, that's a problem. The only way to use it with tbsDropdown is to actually assign a DropDownMenu to the button. Maybe TColorPopup should be inherited from TPopupMenu and instead of popping up a menu you popup the form. But all the normal events should be handled like it is a TPopupMenu to be able to assign this to the DropDownMenu of a TToolButton. Another option would be to assign a "dummy" TPopupMenu to the DropDownMenu and show the form in the OnPopup of that dummy TPopupMenu. ---------------------------------------------------------------------- rvk · 2015-10-12 11:02 Quote from: wp on October 12, 2015, 12:09:03 amA question to the experts: This pseudo popup-menu inherits from a form, and therefore it looks differently from the regular PopupMenus. Is there a way to "hijack" the window opened by a TPopupMenu component and place the buttons into it? I had a quick look at the TJvOfficeColorButton which is included in Jedi/JVCL. It uses a panel to do this. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   TJvCustomOfficeColorButton = class(TJvCustomPanel, IJvHotTrack)  private    FMainButton: TJvColorSpeedButton;    FArrowButton: TJvSpeedButton; ---------------------------------------------------------------------- wp · 2015-10-12 11:30 The TJvCustomOfficeColorButton represents the button with the arrow key, it corresponds to the TToolbutton used by myself. Of course the jvcl button is better because it distinguishes between the button and arrow areas. But it won't integrate into a toolbar as nicely as a TToolbutton child. The office color panel shown in your screen shot, in the end, inherits from a plain old form, with many additions though, but should appear similar to the form of my demo. I'd expect to miss the shadow of a true popup menu as well. (I did not install the huge jcl library in Delphi any more, so I can't tell for sure). My idea was: the popup windows opened from a toolbutton or a menu item, is nothing else than a "window" (in Windows terms). Therefore, it should be possible to insert another control (my color panel) into it. ---------------------------------------------------------------------- rvk · 2015-10-12 14:27 Quote from: wp on October 12, 2015, 01:30:48 pmThe office color panel shown in your screen shot, in the end, inherits from a plain old form, with many additions though, but should appear similar to the form of my demo. Woops, yeah, I've should have looked one line further  Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   TJvCustomOfficeColorButton = class(TJvCustomPanel, IJvHotTrack)  private    FMainButton: TJvColorSpeedButton;    FArrowButton: TJvSpeedButton;    FColorsForm: TJvOfficeColorForm;So TJvOfficeColorButton also has a form. Quote from: wp on October 12, 2015, 01:30:48 pmMy idea was: the popup windows opened from a toolbutton or a menu item, is nothing else than a "window" (in Windows terms). Therefore, it should be possible to insert another control (my color panel) into it. If I look into TPopupMenu it inherits from TMenu (logically) and that one is dependent on the widgetset of the OS. This is not just a "form" in Lazarus which is opened for TPopupMenu. For Windows you end up in lazarus\lcl\interfaces\win32\win32wsmenus.pp. Well, with all the VistaDraw and support for different Windows-version this is going to be a hell to draw something on that window. Even if you could get a "Canvas" to draw on you need to eliminate the menu-items. Not to speak of the cross-platform aspect of it all. It might be easier to just create a TToolButton with style tbsDropdown and hang a dummy TPopupMenu on DropDownMenu. In that dummy TPopupMenu.OnDropDown you can do the opening of the form (and cancel the dropdown of the dummy). Clicking the button itself would use the previous color. This would also be more cross-platform ready. But you could go digging in lazarus\lcl\interfaces\win32\win32wsmenus.pp to see how that's done.