Floating Pop-Up Menus
--Keegan Roth
Thoughts
Free-floating menus require minimal effort on part of the user, opposed to the equivalent of going through the normal menuing system. Through the Visual C++ environment, implementation of floating pop-up menus is a simple and straightforward process.
Overview
In this procedure you will create a single button in a single-document interface and program a pop-up menu to move and re-size the button. This example will show you the basic ideas behind the implementation of floating pop-up menus.
Procedure
First you will create the button that will be on the screen
int x,y,width,height;
CButton Button;
int temp = CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
temp = temp && Button.Create("Test",BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE,CRect(x,y,x+width,y+height),this,100);
return temp;
x = y = 30;
width = height = 50;
You will now create the menu that will be the floating pop-up
You will now link these menu messages to the code you want to implement.
Button was declared as an object of the class CButton, which descends from the CWnd class. For every CWnd object and any object descendent of CWnd is defined a member function MoveWindow that allows the object to be moved and resized. The first and second parameters specifies the new X and Y positions. The third and fourth specifies the new width and height. If you want the button to be invalidated at that time so that it will be re-drawn, you would set the fifth and final parameter to true, otherwise set it to false.
x += 5;
Button.MoveWindow(x,y,width,height,true);
y += 5;
Button.MoveWindow(x,y,width,height,true);
width += 5;
Button.MoveWindow(x,y,width,height,true);
height += 5;
Button.MoveWindow(x,y,width,height,true);
Menus can be retrieved and stored into CMenu objects with a member function LoadMenu(UINT nIDResource). Within each menu there can be multiple entries. A CMenu pointer to these submenus can be retrieved by calling the CMenu member function GetSubMenu(int nPos) after LoadMenu() has been called. NPos refers to the zero-based index position of which menu item to retrieve. Since you only created one entry (Spacial) then you want to retrieve the first index, or zero. To initiate the floating menu the CMenu member function TrackPopupMenu( UINT nFlags, int x, int y, CWnd* pWnd, LPCRECT lpRect = NULL ) is called.
In order to make the floating menu appear only when the user clicks on the button you must first get the button's dimensions with a GetWindowRect() call. The CRect class defines a function called PtInRect(CPoint point) that returns true if point lies within the CRect, false if it does not. With this condition, you can call TrackPopupMenu to do the floating menu only when there is a click on the button.
CMenu Menu;
CMenu *subMenu;
Menu.LoadMenu(IDR_SPACIAL);
CRect rect;
Button.GetWindowRect(rect);
if(rect.PtInRect(point)) {
subMenu = Menu.GetSubMenu(0);
subMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x,point.y,this);
}
You now should have a basic understanding of how a floating pop-up menu is implemented. From this knowledge you can increase the level of functionality in your applications a great deal.