I wonder how this guy has created this toolbar on the program:
this is a modeless dialog created by the guy, I think:
but my dialog is a modal one. I don't think it makes a lot of change!
and this the code written by him to use the toolbar supplied in the res folder:
MainFrm.h
protected: // control bar embedded members
CMFCMenuBar m_wndMenuBar;
CMFCToolBar m_wndToolBar;
CMFCStatusBar m_wndStatusBar;
CMFCToolBarImages m_UserImages;
MainFrm.cpp
the code added in function:CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) to initialize the toolbar supplied in the resource:
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_wndToolBar.LoadToolBar(theApp.m_bHiColorIcons ? IDR_MAINFRAME_256 : IDR_MAINFRAME))
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
CString strToolBarName;
bNameValid = strToolBarName.LoadString(IDS_TOOLBAR_STANDARD);
ASSERT(bNameValid);
m_wndToolBar.SetWindowText(strToolBarName);
CString strCustomize;
bNameValid = strCustomize.LoadString(IDS_TOOLBAR_CUSTOMIZE);
ASSERT(bNameValid);
m_wndToolBar.EnableCustomizeButton(TRUE, ID_VIEW_CUSTOMIZE, strCustomize);
// Allow user-defined toolbars operations:
InitUserToolbars(NULL, uiFirstUserToolBarId, uiLastUserToolBarId);
if (!m_wndStatusBar.Create(this))
{
TRACE0("Failed to create status bar\n");
return -1; // fail to create
}
m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT));
// TODO: Delete these five lines if you don't want the toolbar and menubar to be dockable
m_wndMenuBar.EnableDocking(CBRS_ALIGN_ANY);
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_wndMenuBar);
DockPane(&m_wndToolBar);
// enable Visual Studio 2005 style docking window behavior
CDockingManager::SetDockingMode(DT_SMART);
// enable Visual Studio 2005 style docking window auto-hide behavior
EnableAutoHidePanes(CBRS_ALIGN_ANY);
// Enable toolbar and docking window menu replacement
EnablePaneMenu(TRUE, ID_VIEW_CUSTOMIZE, strCustomize, ID_VIEW_TOOLBAR);
// enable quick (Alt+drag) toolbar customization
CMFCToolBar::EnableQuickCustomization();
if (CMFCToolBar::GetUserImages() == NULL)
{
// load user-defined toolbar images
if (m_UserImages.Load(_T(".\\UserImages.bmp")))
{
CMFCToolBar::SetUserImages(&m_UserImages);
}
}
// enable menu personalization (most-recently used commands)
// TODO: define your own basic commands, ensuring that each pulldown menu has at least one basic command.
CList<UINT, UINT> lstBasicCommands;
lstBasicCommands.AddTail(ID_FILE_NEW);
lstBasicCommands.AddTail(ID_FILE_OPEN);
lstBasicCommands.AddTail(ID_FILE_SAVE);
lstBasicCommands.AddTail(ID_FILE_PRINT);
lstBasicCommands.AddTail(ID_APP_EXIT);
lstBasicCommands.AddTail(ID_EDIT_CUT);
lstBasicCommands.AddTail(ID_EDIT_PASTE);
lstBasicCommands.AddTail(ID_EDIT_UNDO);
lstBasicCommands.AddTail(ID_APP_ABOUT);
lstBasicCommands.AddTail(ID_VIEW_STATUS_BAR);
lstBasicCommands.AddTail(ID_VIEW_TOOLBAR);
CMFCToolBar::SetBasicCommands(lstBasicCommands);
**In fact something that I don't understand and has wasted my time two days and made me to post four questions in this site is that after making a new toolbar supply here:
and leading to the toolbar editor
1-how can I create a new toolbar button here on the toolbar that has been supplied?
2-how can I change the shape of this button to the standard 24bit depth images or to a desired icon?
at last I want to have an image like this for my toolbar in my res folder and surely I want the buttons to be seperately clickable in my program's window.
If there's a need to the source of the project, I have uploaded the guy's project here
The program with mainframe.cpp is not a modeless dialog, it is an MFC doc/view program that is designed to support a menu bar and toolbar.
A dialog-based program does not have the toolbar support designed in. The MFC sample program DLGCBR32 (in MSDN) shows how to put a toolbar on a dialog.
I think it's just a question of reading the proper documentation, create new toolbar button: see MSDN Creating a New Toolbar Button and Toolbar Editor.
Changing the image depth of the buttons in a toolbar: load the bmp file associated with the toolbar (in the Res folder) in a bitmap editor (like Paint), save as a bmp with a different image depth, load the sln in VS and rebuild the project.
Related
So for the simple feat of wanting to put an icon on the right side of button text instead of the left resulted in having to use owner draw buttons (but someone here said Custom Draw is actually available if using visual themes). Okay, fine, but now I'm finding you can't really duplicate what Windows standard buttons do when it's not in owner draw mode.
For a normal enabled button I can get the look correct by checking if visual styles are available or not and then using either the DrawThemeBackground() / DrawThemeText() or DrawFrameControl() / DrawText(). However the hot key underline character is shown even when alt key is not pressed, the default buttons don't show it until alt pressed.
For a disabled button, I can't duplicate the disabled look of the icon placed on the button. I tried DrawState() over DrawIconEx() but that looks like the old Windows 3.1 type grey graphic not the visual style dimmed graphic. I see there is a DrawThemeIcon() for an image list, I guess I could try that (I'd have to test non visual style mode to see if DrawState() matches when not using visual styles).
Also, as you hover over the button, the state doesn't change, I understand that if using owner draw, that doesn't occur, maybe it would still work with Custom Draw?
So the two main questions are:
1 - Is there something built-in to the button / owner draw to handle the underlined hotkey only when alt was pressed?
Update to Question 1: I found DT_HIDEPREFIX in DrawText() and using Custom Draw there is the CDIS_SHOWKEYBOARDCUES flag. However with Owner Draw I'm not sure if there is a flag someplace?
2 - How do you draw an icon for a button that is disabled to match what default buttons do?
TIA!!
For shortcut underline you can use WM_QUERYUISTATE to ask if it should be hidden or visible
DWORD draw_text_flags = ...;
if ( SendMessage( control_hwnd, WM_QUERYUISTATE, 0, 0 ) & UISF_HIDEACCEL ) != 0 )
{
// hide prefix
draw_text_flags |= DT_HIDEPREFIX;
}
// some combination of PBS_DEFAULTED, PBS_DISABLED, PBS_HOT, PBS_NORMAL, PBS_PRESSED;
int state = ...;
DrawThemeText( theme, hdc, BP_PUSHBUTTON, state, text, text_len, draw_text_flags, 0, rect );
Answer to Q2: If you create an HIMAGELIST using ILC_COLOR32 | ILC_MASK, and use ILD_NORMAL|ILD_BLEND25 on ImageList_Draw() it gives the same look as windows default buttons for a disabled button.
Based on responses from #Remy-Lebeau and #Daniel-Sęk and reviewing various projects on CodeProject, I create an easy to use class to handle this. It can be found at CodeProject. Thanks Guys.
Something I thought would be easy I can't get to work. How do I get a ComboBox to show on the CMFCToolBar? Here's what I have done that doesn't work (meaning it just shows the original placeholder button with the circle (grayed out)).
1 - I added a button to the toolbar in resource editor giving it the id ID_EDIT_FIND_COMBO (I also put a circle in it just to know it's in use).
2- in CMainFrame I added ON_REGISTERED_MESSAGE(AFX_WM_RESETTOOLBAR, OnToolbarReset) to message map and the OnToolbarReset() function below:
afx_msg LRESULT CMainFrame::OnToolbarReset(WPARAM wparm, LPARAM )
{
UINT uitoolbarid = (UINT) wparm;
if (uitoolbarid == IDR_MAINFRAME) {
CMFCToolBarComboBoxButton btncombo(ID_EDIT_FIND_COMBO, GetCmdMgr()->GetCmdImage(ID_EDIT_FIND));
m_wndToolBar.ReplaceButton(ID_EDIT_FIND_COMBO, btncombo);
}
return 0;
}
The ReplaceButton() returns 1 saying it replaced it.
What am I missing?
To be clear, here's what MS says to do which is what is done above:
1 - Reserve a dummy resource ID for the button in the parent toolbar resource. For more information about how to create buttons by using the Toolbar Editor in Visual Studio, see the Toolbar Editor article.
2 - Reserve a toolbar image (button icon) for the button in all bitmaps of the parent toolbar.
3 - In the message handler that processes the AFX_WM_RESETTOOLBAR message, do the following steps:
a. Construct the button control by using a CMFCToolbarButton-derived class.
b. Replace the dummy button with the new control by using CMFCToolBar::ReplaceButton. You can construct the button object on the stack, because ReplaceButton copies the button object and maintains the copy.
TIA!!
Here's a sample project where it doesn't work. Just the button on the toolbar, not a combobox. Even took code sample from MS sample.
Sample Project
The answer is that MFC caches the toolbar so if you ever run it without the combo, once you replace the button to use the combo it still doesn't use it. You can make it pick up the change by either going to customize for the toolbars (if you have that option enabled) and choose Reset All, otherwise, you'll find under Computer\HKEY_CURRENT_USER\Software\{NameAsUsedInSetRegistryCall}\{appname}\Workspace all the cache items, of which the various MFCToolBar entries. Delete the key and run app again, then it works. Why they wouldn't make it smart and have a timestamp to know if to automactially update, not sure?
I had created buttons on a dialog using resource editor(using Visual C++,X64) . On the button click event i have to show another window which is exactly of the same size and at same place (For further details i want to tell you that i have two buttons "next" and "previous" . on clicking them i have preview of "Image" and a "File" respectively). My dialog uses the handle of parent which comes from GetWindow function. See this please -
SomeClassOrFounctionNoMatterWhat::GetWindow(HWND *phwnd)
{
HRESULT hr = E_INVALIDARG;
if (phwnd)
{
*phwnd = m_hwndParent; //m_hwndParent is the parent handle now
hr = S_OK;
}
return hr;
}
So i mean the parent handle is m_hwndParent and using this handle i have created Dialog using this-
m_hwndPreview = CreateDialogParam(g_hInst
MAKEINTRESOURCE(IDD_MAINDIALOG),
m_hwndParent,
(DLGPROC)DialogProc,
(LPARAM)this);
and m_hwndPreview contains the button which i have created on the dialog IDD_MAINDIALOG.
and on button click event i am displaying the a file contents like this-
m_hwndPreview3 = CreateWindowExW(0,
MSFTEDIT_CLASS,
NULL, //This window is to display the html file.
WS_CHILD|WS_VISIBLE|WS_VSCROLL|ES_MULTILINE|ES_READONLY|WS_EX_TOPMOST,
m_rcParent.left, m_rcParent.top,
RECTWIDTH(m_rcParent),RECTHEIGHT(m_rcParent),
m_hwndPreview,
NULL,
NULL,
NULL); // similarly m_hwndPreview2 for image preview
See I am using m_hwndPreview as its parent which contains the buttons. I am doing so because i want to have buttons on my every window in order to display different contents by clicking on them.
So my problem is the buttons are created succesfully and are working properly but when i click any button it takes me on different window for the display of the file or Image. But when it takes me on different window the button disappears on the first sight and they appears only when i move mouse over them.
What should i do in order to have the button appearing on every window without moving mouse over them ?
I have an MFC application. In my application if I run on Windows XP it's working fine. But if I run in Windows Vista the MFC dialog hides behind the taskbar.
bool bHide=true;
CRect rectWorkArea = CRect(0,0,0,0);
CRect rectTaskBar = CRect(0,0,0,0);
CWnd* pWnd = CWnd::FindWindow("Shell_TrayWnd", "");
pWnd->ShowWindow(SW_SHOW);
if( bHide )
{ // Code to Hide the System Task Bar
SystemParametersInfo(SPI_GETWORKAREA,0,(LPVOID)&rectWorkArea,0);
if( pWnd )
{
pWnd->GetWindowRect(rectTaskBar);
// rectWorkArea.bottom -= rectTaskBar.Height();
rectWorkArea.bottom += rectTaskBar.Height();//-----to hide taskbar
SystemParametersInfo(SPI_SETWORKAREA,0,(LPVOID)&rectWorkArea,0);
// pWnd->ShowWindow(SW_SHOW);
pWnd->ShowWindow(SW_HIDE); //--to hide taskbar
}
}
I used this code but it hides the taskbar. But I want to show the application above the task bar.
You don't own the taskbar, so you are not supposed to hide it. You have the option to auto-minimize it by the way. You have another option of using secondary monitor without taskbar there.
On the primary monitor your app is given work area, you are being able to locate (judging from the code snippet provided above). It is the best to position your window within this area without interfering with the taskbar, whether it is above or beyond.
If you still feel like making it more like a competition "who is on top" with the task bar, you might want to take a look at SetWindowPos API and window Z-Order.
finally i found the solution , what we want to do is we should add the below code in our oninitdialog,
SetWindowPos(&this->wndTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
the above line is enough to show the mfc dialog on above the taskbar . but sometimes the focus of the dialog get changed looks hanged(no response in dialog) the application.if it occurs put the below code.
SetWindowPos(&this->wndBottom,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
I want to create full screen topmost (screen saver) window with MFC? How to create such full screen window in MFC? I tried to create win32 application and i am able to create fullscreen top most window but i want to create using MFC so later i can put different MFC controls on that window?
Please help me.
Thanks,
Jim.
I think removing the border from the dialog resource and showing the window as maximized (ShowWindow(SW_SHOWMAXIMIZED)) should do the job.
As for topmost use the System Modal style in the dialog resource.
I do it with a Dialog Box app. In the resource editor properties for the dialog resource, set Border=None and Title Bar=False to eliminate all border elements. In OnInitDialog, use the following to resize the dialog to the entire desktop:
CRect rcDesktop;
rcDesktop.left = GetSystemMetrics(SM_XVIRTUALSCREEN);
rcDesktop.right = rcDesktop.left + GetSystemMetrics(SM_CXVIRTUALSCREEN);
rcDesktop.top = GetSystemMetrics(SM_YVIRTUALSCREEN);
rcDesktop.bottom = rcDesktop.top + GetSystemMetrics(SM_CYVIRTUALSCREEN);
MoveWindow(rcDesktop, FALSE);
This code works on multiple monitors, unlike maximizing the window.
No need to worry about making the window topmost, Windows will display it on a dedicated desktop with no other windows present.
You should be able to adapt the example code here to do what you want:
MSDN: Initializing a dialog box