How to create a window that behaves like taskbar? - c++

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

Related

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

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.

How to make WS_THICKFRAME invisible, but still functional in MFC?

So, I created a dialog that has a style: WS_THICKFRAME.
This WS_THICKFRAME gives the dialog box the functionality to resize the window, but my problems is that I don't won't a border around my window to be visible. How would I make the border invisible, but still have the re-size capability?
An example would be most helpful! Thanks!
Below, are the styles of the template for the dialog box I created:
IDD_GADGETTRANSLUCENTDIALOG DIALOGEX 0, 0, 320, 200
STYLE DS_ABSALIGN | DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | WS_SYSMENU | WS_THICKFRAME
Remove WS_THICKFRAME
Handle WM_NCHITTEST roughly as follows:
UINT CMyClass::OnNcHitTest(CPoint point)
{
CRect rWindow;
GetWindowRect(rWindow);
CRect rInner(rWindow);
rInner.DeflateRect(GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER));
if (rWindow.PtInRect(point) && !rInner.PtInRect(point))
{
// figure out which of the following codes to return: //
// HTBOTTOM, HTTOP, HTLEFT, HTRIGHT //
// HTBOTTOMLEFT, HTBOTTOMRIGHT, HTTOPLEFT, HTTOPRIGHT //
}
else
{
return CMyBaseClass::OnNcHitTest(point);
}
}

Win32 API ListView Creation (C++)

I want to create a ListView in c++.
My code so far:
InitCommonControls(); // Force the common controls DLL to be loaded.
HWND list;
// window is a handle to my window that is already created.
list = CreateWindowEx(0, (LPCSTR) WC_LISTVIEWW, NULL, WS_VISIBLE | WS_CHILD | WS_BORDER | LVS_SHOWSELALWAYS | LVS_REPORT, 0, 0, 250, 400, window, NULL, NULL, NULL);
LVCOLUMN lvc;
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvc.iSubItem = 0;
lvc.pszText = "Title";
lvc.cx = 50;
lvc.fmt = LVCFMT_LEFT;
ListView_InsertColumn(list, 0, &lvc);
But if I compile and execute the code, just a blank window is beeing showed. Compiler: MinGW on Windows 7 (x86).
Can anybody help me showing the listview properly?
Here is the link to original MSDN sample code of ListView control written in Windows API and C.
It compiles in VC++ 2010.
WC_LISTVIEWW (notice the extra W on the end) is a wchar_t*, but you are type-casting it to a char*. That will only compile if UNICODE is not defined, making the generic CreateWindowEx() map to CreateWindowExA(). Which means you are trying to create a Unicode window with the Ansi version of CreateWindowEx(). That will not work.
You need to either:
use the generic WC_LISTVIEW so it matches the generic CreateWindowEx(), and get rid of the type-cast:
list = CreateWindowEx(..., WC_LISTVIEW, ...);
keep using WC_LISTVIEWW, but call CreateWindowExW() instead:
list = CreateWindowExW(..., WC_LISTVIEWW, ...);

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.

MFC docking windows and where they dock

I have created (generated) a MDI project with tabbed documents with
VS2008 Pro.
Visual Studio generates an application with the File/Class view
window, properties window, output window and the first MDI document/
view.
I want to control the sides on which the windows dock. I thought this
was done in BOOL CMainFrame::CreateDockingWindows() , i changed the
CBRS_TOP to CBRS_BOTTOM and CBRS_RIGHT to CBRS_LEFT , but the windows
still come out the same in the client area. It makes no difference
what is use for a window style attribute of CBRS_xxxx. Where and how
can i control where in the client area these windows dock ?
I changed then in :
BOOL CMainFrame::CreateDockingWindows()
{
BOOL bNameValid;
// Create class view
CString strClassView;
bNameValid = strClassView.LoadString(IDS_CLASS_VIEW);
ASSERT(bNameValid);
if (!m_wndClassView.Create(strClassView, this, CRect(0, 0, 200, 200), TRUE,ID_VIEW_CLASSVIEW, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{
TRACE0("Failed to create Class View window\n");
return FALSE; // failed to create
}
// Create file view
CString strFileView;
bNameValid = strFileView.LoadString(IDS_FILE_VIEW);
ASSERT(bNameValid);
if (!m_wndFileView.Create(strFileView, this, CRect(0, 0, 200, 200),TRUE, ID_VIEW_FILEVIEW, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT| CBRS_FLOAT_MULTI))
{
TRACE0("Failed to create File View window\n");
return FALSE; // failed to create
}
// Create output window
CString strOutputWnd;
bNameValid = strOutputWnd.LoadString(IDS_OUTPUT_WND);
ASSERT(bNameValid);
if (!m_wndOutput.Create(strOutputWnd, this, CRect(0, 0, 100, 100),
TRUE, ID_VIEW_OUTPUTWND, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_BOTTOM | CBRS_FLOAT_MULTI))
{
TRACE0("Failed to create Output window\n");
return FALSE; // failed to create
}
// Create properties window
CString strPropertiesWnd;
bNameValid = strPropertiesWnd.LoadString(IDS_PROPERTIES_WND);
ASSERT(bNameValid);
if (!m_wndProperties.Create(strPropertiesWnd, this, CRect(0, 0, 200, 200), TRUE, ID_VIEW_PROPERTIESWND, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |CBRS_RIGHT | CBRS_FLOAT_MULTI))
{
TRACE0("Failed to create Properties window\n");
return FALSE; // failed to create
}
SetDockingWindowIcons(theApp.m_bHiColorIcons);
return TRUE;
}
Could someone please help explain to me how to control the sides where
these windows dock?
Thanks.
IIRC, CBRS_TOP etc. are for where they can dock, not for where they are docked when you start the application. That is saved in the registry, basically it will show up where it was when the application was shut down the last time.
In the past (this was not with the Feature Pack docking framework) if you wanted to dock on startup to a specific side you had to set the side where you wanted the toolbar to be docked as the only one allowed (e.g. on the right), create the toolbar, dock it (there was a SetDocked() or something like that) and then modify the allowed dock sides to the directions you wanted to allow. I'm not sure if that behavior persists in the current version but I think it does, as that was something build on low level docking toolbar functionality which the feature pack stuff just builds on.
Not a real answer but hopefully it'll set you on your way...