How can I know the actual size of a menu?
-
How can I know the actual size of a menu? I need to display a menu from a CToolBarCtrl toolbar. When the menu is from top to bottom, the menu should be popped up from the bottom of the bar, on the other hand, when the bar is near the bottom of the screen and the menu needs to be displayed from bottom to top, the menu should be popped up from the top of the bar. IE paints menu this way so that the bar won't be blocked by the menu. But I don't know how to get the acutal size (in pixles) of the menu. Or if I can how which way it pops up the menu, that would be better. Thanks a lot in advance.
-
How can I know the actual size of a menu? I need to display a menu from a CToolBarCtrl toolbar. When the menu is from top to bottom, the menu should be popped up from the bottom of the bar, on the other hand, when the bar is near the bottom of the screen and the menu needs to be displayed from bottom to top, the menu should be popped up from the top of the bar. IE paints menu this way so that the bar won't be blocked by the menu. But I don't know how to get the acutal size (in pixles) of the menu. Or if I can how which way it pops up the menu, that would be better. Thanks a lot in advance.
I beleive that BCMenu By Brent Corkum (@ codeproject) will probably answer your question. The following is from some code I wrote a while ago, it was derivived from Bent Corkum's code (since his was less complicated than my first idea):
BOOL CDialogMenu::TrackWindow()
{
if( m_rcExclude.left == __BADPOSITION )
return FALSE;CRect rectWindow; WINDOWPLACEMENT wndpl; wndpl.length = sizeof(WINDOWPLACEMENT); if( !GetWindowPlacement( &wndpl ) ) return FALSE; rectWindow = wndpl.rcNormalPosition; //GetWindowRect(&rectWindow); int cx = ::GetSystemMetrics(SM\_CXSCREEN); int cy = ::GetSystemMetrics(SM\_CYSCREEN); // Set prefered position rectWindow.SetRect( m\_rcExclude.left,m\_rcExclude.bottom, m\_rcExclude.left+rectWindow.Width(), m\_rcExclude.bottom+rectWindow.Height()); // Center relative to exclusion rectangle? if( m\_bCenter ) rectWindow.OffsetRect(-((rectWindow.Width() + m\_rcExclude.Width())>>1),0); // Too far right? if (rectWindow.right > cx) rectWindow.OffsetRect(-(rectWindow.right - cx), 0); // Too far left? if (rectWindow.left < 0) rectWindow.OffsetRect( -rectWindow.left, 0); // Too far down? Move to top of exclustion rectangle. if (rectWindow.bottom > cy) rectWindow.OffsetRect(0,-(m\_rcExclude.Height() + rectWindow.Height())); // Move to new position //MoveWindow(rectWindow, TRUE); wndpl.rcNormalPosition = rectWindow; SetWindowPlacement( &wndpl ); return FALSE;
}
I hope this helps! Good luck! INTP
-
How can I know the actual size of a menu? I need to display a menu from a CToolBarCtrl toolbar. When the menu is from top to bottom, the menu should be popped up from the bottom of the bar, on the other hand, when the bar is near the bottom of the screen and the menu needs to be displayed from bottom to top, the menu should be popped up from the top of the bar. IE paints menu this way so that the bar won't be blocked by the menu. But I don't know how to get the acutal size (in pixles) of the menu. Or if I can how which way it pops up the menu, that would be better. Thanks a lot in advance.
Here's what I use in the CP SearchBar:
void CalcMenuLocation ( HMENU menu, const RECT& rcBtn,
POINT& ptMenuLocation, UINT& uFlags )
{
POINT pt = { rcBtn.left, rcBtn.bottom };
UINT uMenuFlags = 0;
UINT uItemCnt = GetMenuItemCount ( menu );
int nMenuHeight = uItemCnt * GetSystemMetrics ( SM_CYMENUSIZE );
int nScreenHeight = GetSystemMetrics ( SM_CYSCREEN );if ( nMenuHeight + pt.y > nScreenHeight ) { // Reposition the menu so its bottom is aligned with the top // edge of the button. uMenuFlags |= TPM\_BOTTOMALIGN; pt.y = rcBtn.top; } ptMenuLocation = pt; uFlags |= uMenuFlags;
}
Call it like this:
LRESULT CSearchBar::OnToolbarDropdown ( NMHDR* phdr )
{
NMTOOLBAR* pnmtb = (NMTOOLBAR*) phdr;
HMENU hmenu, hPopup;
RECT rcItem = pnmtb->rcButton;hmenu = AtlLoadMenu ( IDR\_YOUR\_MENU\_HERE ); if ( NULL == hmenu ) return TBDDRET\_DEFAULT; hPopup = GetSubMenu ( hmenu, 0 ); ATLASSERT ( NULL != hPopup );
POINT ptMenuLocation;
UINT uFlags = TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RETURNCMD;
int nMenuItem;ClientToScreen ( &rcItem ); CalcMenuLocation ( hPopup, rcItem, ptMenuLocation, uFlags ); nMenuItem = (int) TrackPopupMenu ( hPopup, uFlags, ptMenuLocation.x, ptMenuLocation.y, 0, m\_hWnd, NULL );
}
Note that this is not multi-monitor aware. I don't have 2 monitors at home so I haven't fixed the code to work on secondary monitors. --Mike-- Personal stuff:: Ericahist | Homepage Shareware stuff:: 1ClickPicGrabber | RightClick-Encrypt CP stuff:: CP SearchBar v2.0.2 | C++ Forum FAQ ---- There is a saying in statistics that a million monkeys pounding on typewriters would eventually create a work of Shakespeare. Thanks to the Internet, we now know that this is not true.
-
Here's what I use in the CP SearchBar:
void CalcMenuLocation ( HMENU menu, const RECT& rcBtn,
POINT& ptMenuLocation, UINT& uFlags )
{
POINT pt = { rcBtn.left, rcBtn.bottom };
UINT uMenuFlags = 0;
UINT uItemCnt = GetMenuItemCount ( menu );
int nMenuHeight = uItemCnt * GetSystemMetrics ( SM_CYMENUSIZE );
int nScreenHeight = GetSystemMetrics ( SM_CYSCREEN );if ( nMenuHeight + pt.y > nScreenHeight ) { // Reposition the menu so its bottom is aligned with the top // edge of the button. uMenuFlags |= TPM\_BOTTOMALIGN; pt.y = rcBtn.top; } ptMenuLocation = pt; uFlags |= uMenuFlags;
}
Call it like this:
LRESULT CSearchBar::OnToolbarDropdown ( NMHDR* phdr )
{
NMTOOLBAR* pnmtb = (NMTOOLBAR*) phdr;
HMENU hmenu, hPopup;
RECT rcItem = pnmtb->rcButton;hmenu = AtlLoadMenu ( IDR\_YOUR\_MENU\_HERE ); if ( NULL == hmenu ) return TBDDRET\_DEFAULT; hPopup = GetSubMenu ( hmenu, 0 ); ATLASSERT ( NULL != hPopup );
POINT ptMenuLocation;
UINT uFlags = TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RETURNCMD;
int nMenuItem;ClientToScreen ( &rcItem ); CalcMenuLocation ( hPopup, rcItem, ptMenuLocation, uFlags ); nMenuItem = (int) TrackPopupMenu ( hPopup, uFlags, ptMenuLocation.x, ptMenuLocation.y, 0, m\_hWnd, NULL );
}
Note that this is not multi-monitor aware. I don't have 2 monitors at home so I haven't fixed the code to work on secondary monitors. --Mike-- Personal stuff:: Ericahist | Homepage Shareware stuff:: 1ClickPicGrabber | RightClick-Encrypt CP stuff:: CP SearchBar v2.0.2 | C++ Forum FAQ ---- There is a saying in statistics that a million monkeys pounding on typewriters would eventually create a work of Shakespeare. Thanks to the Internet, we now know that this is not true.
Mike, I am in the process of writing an article about menus. Would I be able to make use of this code as part of it? It would be a good complement to some of the stuff I already have complete. Roger Allen - Sonork 100.10016 Strong Sad: Clever I am? Next to no one. Undiscovered and soggy. Look up. Look down. They're around. Probably laughing. Still, bright, watery. Listed among the top. Ten. Nine. Late night. Early morn. Early mourn. Now I sleep.
-
Mike, I am in the process of writing an article about menus. Would I be able to make use of this code as part of it? It would be a good complement to some of the stuff I already have complete. Roger Allen - Sonork 100.10016 Strong Sad: Clever I am? Next to no one. Undiscovered and soggy. Look up. Look down. They're around. Probably laughing. Still, bright, watery. Listed among the top. Ten. Nine. Late night. Early morn. Early mourn. Now I sleep.
Roger Allen wrote: Mike, I am in the process of writing an article about menus. Would I be able to make use of this code as part of it? Sure, go right ahead :) --Mike-- Personal stuff:: Ericahist | Homepage Shareware stuff:: 1ClickPicGrabber | RightClick-Encrypt CP stuff:: CP SearchBar v2.0.2 | C++ Forum FAQ ---- Pinky, are you pondering what I'm pondering? I think so Brain, but if we shaved our heads, we'd look like weasels!