How should I change the IMAGE(doesn't matter the type) of the button in the toolbar in MFC applications? - c++

I know that this is stupid problem but I am stuck with it for the past 4 days. Why it is so complicated to just modify the toolbar in the MFC apps?
I create New Visual studio MFC application that is dialog based. I create new Toolbar resource. And then how should I set images(png, bitmap, jpeg...) or whatever type to be used in my toolbar?
I have set size to w50 and h50 and I can draw inside the buttons. But I cant find way to use image.
Instead this 2 buttons that I have just tried if its working, I want to use 8 images that are in bitmap format and in png. I read somewhere that PNG is not supported by MFC applications so I converted to Bitmap.
I load my toolbar in the dialog app like this in the OnInitDialog() method:
DWORD dwCtrlStyle = TBSTYLE_FLAT | TBSTYLE_TOOLTIPS | CBRS_SIZE_DYNAMIC;
DWORD dwStyle = AFX_DEFAULT_TOOLBAR_STYLE;
CMFCToolBar::m_dblLargeImageRatio = 1;
if (m_ToolBar.CreateEx(this, dwCtrlStyle, dwStyle, CRect(1, 1, 1, 1), IDR_TOOLBAR1))
{
dwStyle = CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC;
m_ToolBar.SetPaneStyle(m_ToolBar.GetPaneStyle() | dwStyle);
CMFCToolBarInfo info;
m_ToolBar.LoadToolBarEx(IDR_TOOLBAR1, info, FALSE);
CSize sizeToolBar = m_ToolBar.CalcFixedLayout(TRUE, TRUE);
m_ToolBar.SetWindowPos(NULL, 0, 0, sizeToolBar.cx, sizeToolBar.cy, SWP_NOACTIVATE |
SWP_NOZORDER);
CPoint ptOffset(0, sizeToolBar.cy);
}
Please if someone can help me I would be really grateful. The image format doesn't matter. I just want to put image in the toolbar.
This is my app currently:
UPDATE: I have tried this way. ID_BUTTON_1 if the first button in the toolbar and i tried to change its image. But with this there is no button in the toolbar at the place for the first button. What I am doing Wrong?
VERIFY(m_toolbar.LoadBitmap(IDB_BITMAP1));
CMFCToolBarButton mbutton;
mbutton.SetImage(m_toolbar.GetImages()->GetCount() - 1);
m_toolbar.ReplaceButton(ID_BUTTON_1, CMFCToolBarButton(ID_BUTTON_1, 0));

I answered this recently and can no longer find my answer. You can use PNG images for your toolbars. Under the hood you still use the BMP version for the resource editor to create your event handlers etc. But you can then add your PNG as a resource and then load it into your dialog.
For example, I call this in my OnInitDialog function:
void CMeetingScheduleAssistantDlg::CreateToolbar()
{
DWORD dwCtrlStyle = TBSTYLE_FLAT | TBSTYLE_TOOLTIPS | CBRS_SIZE_DYNAMIC;
DWORD dwStyle = AFX_DEFAULT_TOOLBAR_STYLE;
CMFCToolBar::m_dblLargeImageRatio = 1; // AJT v20.1.7 Bug fix
if (m_ToolBar.CreateEx(this, dwCtrlStyle,
dwStyle, CRect(1, 1, 1, 1), IDR_TOOLBAR))
{
dwStyle = CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC;
m_ToolBar.SetPaneStyle(m_ToolBar.GetPaneStyle() | dwStyle);
CMFCToolBarInfo info;
info.m_uiColdResID = IDB_PNG_MAIN_TOOLBAR;
info.m_uiHotResID = IDB_PNG_MAIN_TOOLBAR;
info.m_uiLargeColdResID = IDB_PNG_MAIN_TOOLBAR;
info.m_uiLargeHotResID = IDB_PNG_MAIN_TOOLBAR;
m_ToolBar.LoadToolBarEx(IDR_TOOLBAR, info, FALSE);
CSize sizeToolBar = m_ToolBar.CalcFixedLayout(TRUE, TRUE);
m_ToolBar.SetWindowPos(NULL, 0, 0, sizeToolBar.cx, sizeToolBar.cy,
SWP_NOACTIVATE | SWP_NOZORDER);
// Move all controls down
CPoint ptOffset(0, sizeToolBar.cy);
CRect rcChild;
CWnd* pwndChild = GetWindow(GW_CHILD);
while (pwndChild)
{
if (pwndChild->GetSafeHwnd() != m_ToolBar.GetSafeHwnd())
{
pwndChild->GetWindowRect(rcChild);
ScreenToClient(rcChild);
rcChild.OffsetRect(ptOffset);
pwndChild->MoveWindow(rcChild, FALSE);
}
pwndChild = pwndChild->GetNextWindow();
}
// Resize the window
CRect rcWindow;
GetWindowRect(rcWindow);
rcWindow.bottom += sizeToolBar.cy;
MoveWindow(rcWindow, FALSE);
}
}
I don't know where my previous answer has gone to, else I would have flagged this as duplicate. #confused.

Related

CMFCToolBar LoadToolBarEx fails for toolbar in CDialogEx

I'm trying to use LoadToolBarEx however it always return 0 and no images appear in the toolbar, however if I use LoadBitmap the images load into the toolbar just fine.
My resource image is a PNG 32bit, 32x128 pixels, giving 4 button images.
When using LoadToolBarEx:
When using LoadBitmap:
Contained in OnInitDialog:
DWORD dwCtrlStyle = TBSTYLE_FLAT | TBSTYLE_TOOLTIPS | CBRS_SIZE_DYNAMIC;
DWORD dwStyle = AFX_DEFAULT_TOOLBAR_STYLE;
if (m_ToolBar.CreateEx(this, dwCtrlStyle,
dwStyle, CRect(1, 1, 1, 1), IDR_TOOLBAR1_PNG))
{
dwStyle = CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC;
m_ToolBar.SetPaneStyle(m_ToolBar.GetPaneStyle() | dwStyle);
}
CMFCToolBarInfo info;
m_ToolBar.SetSizes(CSize(32, 32), CSize(32, 32));
BOOL ret1 = m_ToolBar.LoadToolBarEx(IDR_TOOLBAR1_PNG,info,FALSE); // << THIS FAILS
BOOL ret2 = m_ToolBar.LoadBitmap(IDR_TOOLBAR1_PNG); // << THIS WORKS
CMFCToolBarButton but1(0, 0, L"HELLO", TRUE, 0);
CMFCToolBarButton but2(1, 1, L"HELLO", TRUE, 0);
CMFCToolBarButton but3(2, 2, L"HELLO", TRUE, 0);
but3.SetStyle(but3.m_nStyle | TBBS_DISABLED);
m_ToolBar.InsertButton(but1, 0);
m_ToolBar.InsertButton(but2, 0);
m_ToolBar.InsertButton(but3, 0);
m_ToolBar.SetToolBarBtnText(0, _T("By"));
m_ToolBar.SetToolBarBtnText(1, _T("Your"));
m_ToolBar.SetToolBarBtnText(2, _T("Command"));
m_ToolBar.InsertSeparator(2);
m_ToolBar.SetWindowPos(0, 0, 0, 400, 36, 0, 0);
In the TestDlg.rc I have:
//////////////////////////////////////////////////
//
// PNG
//
IDR_TOOLBAR1_PNG PNG "res\\toolbarNEW.png"
//////////////////////////////////////////////////
//
// Toolbar
//
//////////////////////////////////////////////////
In resource.h:
#define IDR_TOOLBAR1_PNG 135
What could be causing LoadToolBarEx to fail? there is no useful error code to work from, and I've tried various image format combinations so I don't believe it's an issue with the image resource.

How to create a window that behaves like taskbar?

I want to ask how to create a window that behaves like taskbar (shell_traywnd)?
In a windows app called Enable Viacam (camera mouse for disabled people) I saw that the app creates a taskbar-like window on the top of the screen (see the image below) which pulls all other windows underneath it.
Enable_Viacam's window (top of screen)
I used Winspector software to examine this Enable Viacam's window to see its WS_/WS_EX_ properties so that I would try emulate it, but calling CreateWindowEx with those properties didn't give me the wanted result..
Here's my attempt (message loop & window procedure not shown here)
hwnd = CreateWindowEx(
WS_EX_TOOLWINDOW | WS_EX_TOPMOST | WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_CONTROLPARENT,
"#32770","Window",
WS_OVERLAPPEDWINDOW | WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_BORDER | DS_3DLOOK,
0, /* x */
0, /* y */
GetSystemMetrics(SM_CXSCREEN), /* width */
50, /* height */
NULL,NULL,hInstance,NULL);
Any ideas greatly appreciated,
thank you!
Apparently this window type is called an appbar
I created window with style WS_EX_TOOLWINDOW and WS_POPUP and followed that MSDN link
My code now is
APPBARDATA abd = {0};
abd.cbSize = sizeof(APPBARDATA);
abd.hWnd = hwnd;
abd.uCallbackMessage = 888;
SHAppBarMessage(ABM_NEW, &abd);
abd.uEdge = ABE_TOP;
abd.rc.left = 0;
abd.rc.right = GetSystemMetrics(SM_CXSCREEN);
abd.rc.top = 0;
abd.rc.bottom = height;
SHAppBarMessage(ABM_QUERYPOS, &abd);
abd.rc.bottom = abd.rc.top + height;
SHAppBarMessage(ABM_SETPOS, &abd);
Have fun coding guys

How do I refresh MFC dialog before Sleep() call

I have an array of buttons holding bitmap images.
I'm trying to change the image of one of the buttons to a different image for one second, and then change it again - but during the sleep, the UI still displays the older image as if I hadn't changed it - this means I don't see bmp_explosion displayed at all.
void COOPFinalDlg::ShowExplosion(int position)
{
SetButtonImage(position, bmp_explosion);
Sleep(1000);
SetButtonImage(position, bmp_tile);
}
void COOPFinalDlg::SetButtonImage(int buttonId, int imageId)
{
CButton* button = buttons[buttonId - ButtonRangeStart];
CBitmap bmp;
bmp.LoadBitmap(imageId);
button->SetBitmap(bmp);
}
The buttons were initalized to a bitmap the following way:
CBitmap bmp;
bmp.LoadBitmap(bmp_tile);
CRect rect(....);
CButton* button = new CButton;
button->Create(NULL, WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | DT_CENTER | WS_BORDER, rect, this, idCounter++);
button->ModifyStyle(0, BS_BITMAP);
button->SetBitmap(bmp);
buttons.Add(button);

Unable to change Tab's label Text of VC++ CMFCOutlookBar

Its been a while i have stopped working on VC++ and now i have some project which i have again started my development on VC++.... I am having a strange issue right now the label of the control is not getting change at all here is my code for initialization of mfcoutlookbar
BOOL CMainFrame::CreateOutlookBar(CMFCOutlookBar& bar, UINT uiID, CMFCShellTreeCtrl& tree, CCalendarBar& calendar,CListCtrlBar &listctrl,int nInitialWidth)
{
bar.SetMode2003();
BOOL bNameValid;
CString strTemp;
bNameValid = strTemp.LoadString(IDS_SHORTCUTS);
ASSERT(bNameValid);
if (!bar.Create(strTemp, this, CRect(0, 0, nInitialWidth, 32000), uiID, WS_CHILD | WS_VISIBLE | CBRS_LEFT))
{
return FALSE; // fail to create
}
CMFCOutlookBarTabCtrl* pOutlookBar = (CMFCOutlookBarTabCtrl*)bar.GetUnderlyingWindow();
if (pOutlookBar == NULL)
{
ASSERT(FALSE);
return FALSE;
}
pOutlookBar->EnableInPlaceEdit(FALSE); //we dont want editing
static UINT uiPageID = 1;
// can float, can autohide, can resize, CAN NOT CLOSE
DWORD dwStyle = AFX_CBRS_FLOAT | AFX_CBRS_AUTOHIDE | AFX_CBRS_RESIZE;
CRect rectDummy(0, 0, 0, 0);
const DWORD dwTreeStyle = WS_CHILD | WS_VISIBLE | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS;
//Create tree
tree.Create(dwTreeStyle, rectDummy, &bar, 1200);
//bNameValid = strTemp.LoadString(IDS_FOLDERS);
ASSERT(bNameValid);
pOutlookBar->AddControl(&tree, L"Folders", 2, TRUE, dwStyle);
//create calender
calendar.Create(rectDummy, &bar, 1201);
// bNameValid = strTemp.LoadString(IDS_CALENDAR);
// ASSERT(bNameValid);
pOutlookBar->AddControl(&calendar, L"CALLLLLL",1, TRUE, dwStyle);
//create list control bar
listctrl.Create(rectDummy,&bar,1202);
// bNameValid = strTemp.LoadString(IDS_DASHBOARD);//Dashboard to check the statistics and statical reports
// ASSERT(bNameValid);
pOutlookBar->AddControl(&listctrl, L"Some", 0, TRUE, dwStyle); //the digit represent icon
bar.SetPaneStyle(bar.GetPaneStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
pOutlookBar->SetImageList(theApp.m_bHiColorIcons ? IDB_PAGES_HC : IDB_PAGES, 24);
pOutlookBar->SetToolbarImageList(theApp.m_bHiColorIcons ? IDB_PAGES_SMALL_HC : IDB_PAGES_SMALL, 16);
pOutlookBar->RecalcLayout();
BOOL bAnimation = theApp.GetInt(_T("OutlookAnimation"), TRUE);
CMFCOutlookBarTabCtrl::EnableAnimation(bAnimation);
bar.SetButtonsFont(&afxGlobalData.fontBold);
return TRUE;
}
if you see i am using two different controls by providing them the text label e,,g,
pOutlookBar->AddControl(&listctrl, L"Some", 0, TRUE, dwStyle);
and the other is
pOutlookBar->AddControl(&calendar, L"CALLLLLL",1, TRUE, dwStyle);
now the label "Some" and "CALLLLLL" is not being displayed i have tried everything but i dont know why its still displaying the default text of
"Calenders" and "Folders"
I have changed all the text inside String table as well ...this code is generated by Visual Studio C++ by wizard using Office 2000.
What is the mistake i am doing???
Okay finally figured out the problem is the cache , the outlookbased bar for any application save the caption and label in registry...so cleaning your solution rebuilding it again and again will not give you the right tabs captions unless you delete the registry entries for that application.
HKEY_USERS\S-1-5-21-3153867254-3211561466-2840709754-1000\Software\Local AppWizard-Generated Applications\test2
and then delete this test2 project key ....after that run your application it will display the correct label.

Is there a graceful way to handle toggling between fullscreen and windowed mode in a Windows OpenGL application?

I'm wondering if it's possible to toggle back and forth between fullscreen mode and windowed mode in an OpenGL window(I'm writing for Windows using C++ and win32), without destroying the OpenGL context, and thus having to reload assets(Textures, VBOs, etc) in the process?
This is undesirable because it introduces a delay in switching between fullscreen and windowed mode, potentially a long one, as well as making it easier to screw things up by forgetting to reinitialize something.
As a followup to that, are there certain visual effects that are broken by managing to do this?
I've done a fair bit of searching and reading for the past few days, and despite a lot of flaming of SDL and other frameworks for having the same problem(I'm not using them anyway, but...), the best I've managed to find is a possible lead on opening a 1x1 window in the background to retain the context while a secondary window is destroyed or created at whim. And that's seeming unreliable from the comments I found regarding it, and seems very kludgey regardless.
Is there a proper way to do this, or is the proper way the often-given-as-an-example method of destroying your window, and recreating it, including destroying your OpenGL context and recreating it?
Basically it's just resizing the window and specifying flags that the border is invisible.
SetWindowLongPtr(hWnd, GWL_STYLE,
WS_SYSMENU | WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE);
MoveWindow(hWnd, 0, 0, width, height, TRUE);
to set it back:
RECT rect;
rect.left = 0;
rect.top = 0;
rect.right = width;
rect.bottom = height;
SetWindowLongPtr(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE);
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
MoveWindow(hWnd, 0, 0, rect.right-rect.left, rect.bottom-rect.top, TRUE);
or for a not-resizable window:
SetWindowLongPtr(hWnd, GWL_STYLE, WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE);
AdjustWindowRect(&rect, WS_CAPTION | WS_POPUPWINDOW, FALSE);
MoveWindow(hWnd, 0, 0, rect.right-rect.left, rect.bottom-rect.top, TRUE);
and then just resize your OpenGL viewport settings.
If you want to set the display mode too, use this:
// change display mode if destination mode is fullscreen
if (fullscreen) {
DEVMODE dm;
dm.dmSize = sizeof(DEVMODE);
dm.dmPelsWidth = width;
dm.dmPelsHeight = height;
dm.dmBitsPerPel = bitsPerPixel;
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
success = ChangeDisplaySettings(&dm, 0) == DISP_CHANGE_SUCCESSFUL;
}
// reset display mode if destination mode is windowed
if (!fullscreen)
success = ChangeDisplaySettings(0, 0) == DISP_CHANGE_SUCCESSFUL;
Here's the code I use, which uses SetWindowPos() rather than MoveWindow(), as discussed in the comments of the other answer.
void enter_fullscreen(application* App)
{
POINT Point = {0};
HMONITOR Monitor = MonitorFromPoint(Point, MONITOR_DEFAULTTONEAREST);
MONITORINFO MonitorInfo = { sizeof(MonitorInfo) };
if (GetMonitorInfo(Monitor, &MonitorInfo)) {
DWORD Style = WS_POPUP | WS_VISIBLE;
SetWindowLongPtr(App->Window, GWL_STYLE, Style);
SetWindowPos(App->Window, 0, MonitorInfo.rcMonitor.left, MonitorInfo.rcMonitor.top,
MonitorInfo.rcMonitor.right - MonitorInfo.rcMonitor.left, MonitorInfo.rcMonitor.bottom - MonitorInfo.rcMonitor.top,
SWP_FRAMECHANGED | SWP_SHOWWINDOW);
}
App->IsFullscreen = true;
}
void exit_fullscreen(application* App)
{
bool WasMaximized = App->IsMaximized;
DWORD Style = WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN;
if (WasMaximized) {
Style = Style | WS_MAXIMIZE;
}
ivec2 WindowPosition = WasMaximized ? App->WindowPosition : App->NormalWindowPosition;
ivec2 WindowSize = WasMaximized ? App->WindowSize : App->NormalWindowSize;
SetWindowLongPtr(App->Window, GWL_STYLE, Style);
SetWindowPos(App->Window, 0,
WindowPosition.X, WindowPosition.Y, WindowSize.X, WindowSize.Y,
SWP_FRAMECHANGED | SWP_SHOWWINDOW);
App->IsFullscreen = false;
}
I call it on F11, but also on WM_ACTIVATE. Otherwise the window would sometimes keep rendering on top on Windows 7, even if another application would receive all messages, including mouse and keyboard.