Visual Style for Windows Explorer hover and selection - winapi

The last three versions of Windows have all had translucent highlight and hover effects in Windows Explorer listview:
Using a theme explorer I see that the ListItem has no state that matches what i see in Windows:
Is there a:
class
part
state
that represents the ListView in Windows?

For compatibility reasons ListView still has the old style look by default. DrawThemeBackground(htheme, hdc, LVP_LISTITEM, ...) will simply draw a solid rectangle with border, for all item states, as shown in above image. GetSysColor should be used to get the right colors for this listview.
A call to SetWindowTheme(hwnd, L"Explorer", NULL) will load the new theme data and draw the list items similar to Explorer. Example:
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
SetWindowTheme(hwnd, L"Explorer", NULL);
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
auto hdc = BeginPaint(hwnd, &ps);
HTHEME ht = OpenThemeData(hwnd, L"LISTVIEW");
if(ht)
{
RECT rc = { 10, 10, 100, 50 };
DrawThemeBackground(ht, hdc, LVP_LISTITEM, LISS_SELECTED, &rc, NULL); OffsetRect(&rc, 0, 55);
DrawThemeBackground(ht, hdc, LVP_LISTITEM, LISS_DISABLED, &rc, NULL); OffsetRect(&rc, 0, 55);
DrawThemeBackground(ht, hdc, LVP_LISTITEM, LISS_SELECTED, &rc, NULL); OffsetRect(&rc, 0, 55);
DrawThemeBackground(ht, hdc, LVP_LISTITEM, LISS_HOT, &rc, NULL); OffsetRect(&rc, 0, 55);
DrawThemeBackground(ht, hdc, LVP_LISTITEM, LISS_HOTSELECTED, &rc, NULL); OffsetRect(&rc, 0, 55);
DrawThemeBackground(ht, hdc, LVP_LISTITEM, LISS_SELECTEDNOTFOCUS, &rc, NULL);
CloseThemeData(ht);
}
EndPaint(hwnd, &ps);
return 0;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
Output:

Related

Creating a filled rectangle with WINAPI

I have created a window using the Win32 API, with a painted Text and a Button. If the button is pressed, it will be deleted, and the text should be overlayed by a filled rectangle.
The button disappearing works fine, but the position of the rectangle is the position of the button. No matter if I change the values of:
RECT rect = { 50, 120, 450, 15 };
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT uiMessage, WPARAM wParam, LPARAM lParam)
{
static HWND hWndButton;
static HWND hWndEditBox;
switch (uiMessage)
{
case WM_CREATE:
hWndButton = CreateWindow(TEXT("BUTTON"), TEXT("Los geht's !"),
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
240, 50, 120, 40, hWnd,
reinterpret_cast<HMENU>(BTN_MAIN_BUTTON_ID),
reinterpret_cast<HINSTANCE>(GetWindowLongPtr(hWnd, GWL_HINSTANCE)),
NULL);
return (0);
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
SetBkMode(hdc, TRANSPARENT);
SetTextColor(hdc, RGB(0, 0, 0));
SetTextAlign(hdc, TA_CENTER);
TextOut(hdc, 300, 10, TEXT("Bitte legen Sie ihr Mitarbeiterprofil an."), lstrlen(TEXT("Bitte legen Sie ihr Mitarbeiterprofil an.")));
EndPaint(hWnd, &ps);
return (0); }
case WM_COMMAND:
if (wParam == BTN_MAIN_BUTTON_ID)
{
DestroyWindow(hWndButton);
PAINTSTRUCT ps2;
HDC hdc = BeginPaint(hWnd, &ps2);
RECT rect = { 50, 120, 450, 15 };
HBRUSH brush = CreateSolidBrush(RGB(50, 151, 151));
GetClientRect(hWnd, &rect);
FillRect(hdc, &rect, brush);
DeleteObject(brush);
EndPaint(hWnd, &ps2);
int i;
char string[20];
for (i = 0; i< profilEinheiten; i++)
{
hWndEditBox = CreateWindow(
TEXT("EDIT"), TEXT("Edit Boxes"),
WS_VISIBLE | WS_CHILD,
100, 40+(20*i), 100, 15, hWnd,
(HMENU)IDC_EDITBOX_TEXT,
(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
NULL);
}
return (0);
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
return (0);
}
return (DefWindowProc(hWnd, uiMessage, wParam, lParam));
}

winapi - painting rich edit thin border

By default a rich edit control has a "3d" border. I draw a thin border around a rich edit control this way:
if (message == WM_NCPAINT)
{
RECT rc;
HDC hdc;
HPEN pen;
HBRUSH brush;
HGDIOBJ oldP, oldB;
POINT tl, br;
::GetWindowRect(hWnd, &rc);
hdc = ::GetDC(hWnd);
tl.x = rc.left;
tl.y = rc.top;
br.x = rc.right;
br.y = rc.bottom;
::ScreenToClient(hWnd, &tl);
::ScreenToClient(hWnd, &br);
pen = ::CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
brush = (HBRUSH) ::GetStockObject(HOLLOW_BRUSH);
oldP = ::SelectObject(hdc, pen);
oldB = ::SelectObject(hdc, brush);
::Rectangle(hdc, tl.x, tl.y, br.x, br.y);
::SelectObject(hdc, oldP);
::SelectObject(hdc, oldB);
::DeleteObject(pen);
::ReleaseDC(hWnd, hdc);
return 0;
}
The border looks fine but the area under the old border is not redrawn. It looks like I have to redraw to whole content of the rich edit control. After that a text shouldn't be a litte bit cut from the bottom. Here you can see what I mean (the second rich edit control has custom border). How to achieve it ?
GetDC returns DC for client area. In this case you need GetWindowDC for the whole richedit window.
Either way, overriding border color in edit and rich-edit can be difficult, because you also have to handle scrollbar painting in WM_NCPAINT
Assuming you don't need vertical and/or horizontal scrollbar, use GetWindowDC as follows:
LRESULT CALLBACK RichEditProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
UINT_PTR, DWORD_PTR)
{
static int border_thickness = 1;
switch(msg)
{
case WM_NCPAINT:
{
HDC hdc = GetWindowDC(hwnd);
RECT rc;
GetClientRect(hwnd, &rc);
rc.right += 2 * border_thickness + 1;
rc.bottom += 2 * border_thickness + 1;
HBRUSH hbrush = (HBRUSH)GetStockObject(NULL_BRUSH);
HPEN hpen = CreatePen(PS_SOLID, 2 * border_thickness, RGB(255, 0, 0));
HBRUSH oldbrush = (HBRUSH)SelectObject(hdc, hbrush);
HPEN oldpen = (HPEN)SelectObject(hdc, hpen);
Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);
SelectObject(hdc, oldpen);
SelectObject(hdc, oldbrush);
DeleteObject(hpen);
DeleteObject(hbrush);
ReleaseDC(hwnd, hdc);
return 0;
}
case WM_NCCALCSIZE:
if(lp)
{
NCCALCSIZE_PARAMS* sz = (NCCALCSIZE_PARAMS*)lp;
InflateRect(&sz->rgrc[0], -border_thickness, -border_thickness);
return 0;
}
break;
case WM_NCDESTROY:
RemoveWindowSubclass(hwnd, RichEditProc, 0);
break;
}
return DefSubclassProc(hwnd, msg, wp, lp);
}
By default, WM_NCCALCSIZE is not called in subclass procedure, you have to call SetWindowPos with SWP_FRAMECHANGED
HWND hrichedit = CreateWindowEx(...);
SetWindowSubclass(hrichedit, RichEditProc, 0, 0);
SetWindowPos(hrichedit, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
If you do need horizontal/vertical scrollbar, you might consider using a borderless richedit, then paint around the rich control in parent window's WM_PAINT procedure.

How to paint over white line between menu bar and client area of window?

I tried to color customize menu items (pure WinAPI). But there is a line in the menu bar which does not draw with MenuInfo.hbrBack color. If the mouse cursor hover above items a part of this line is redrawn. But if I resize the window the line will return. And in the area of menu bar where no items the line drawn constantly. How can I draw over this annoying line?
#include <windows.h>
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
struct
{
COLORREF text = RGB(200, 200, 250);
COLORREF clientBorder = RGB(120, 0, 0);
COLORREF clientBackground = RGB(100, 100, 100);
COLORREF itemBorder = RGB(0, 0, 255);
COLORREF itemBackground = RGB(0, 120, 0);
COLORREF pink = RGB(255, 0, 255);
} colorTheme;
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
WNDCLASSEX wc;
wc.cbSize = sizeof(wc);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.lpszMenuName = NULL;
wc.lpszClassName = "MainWindow";
wc.cbWndExtra = NULL;
wc.cbClsExtra = NULL;
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = CreateSolidBrush(colorTheme.clientBackground);
wc.hInstance = hInst;
RegisterClassEx(&wc);
HWND hMainWnd = CreateWindow(
"MainWindow",
"MainWindow",
WS_OVERLAPPEDWINDOW,
100, 100, 450, 120,
(HWND)NULL, NULL, HINSTANCE(hInst), NULL);
HMENU hMenu = CreateMenu();
HMENU hMenuSub1 = CreatePopupMenu();
HMENU hMenuSub2 = CreatePopupMenu();
HMENU hMenuSub3 = CreatePopupMenu();
AppendMenu(hMenu, MF_OWNERDRAW | MF_POPUP, (UINT)hMenuSub1, "SubMenu1");
AppendMenu(hMenuSub1, MF_OWNERDRAW, 0, "Item01");
AppendMenu(hMenuSub1, MF_OWNERDRAW, 0, "Item02");
AppendMenu(hMenuSub1, MF_OWNERDRAW, 0, "Item03");
AppendMenu(hMenuSub1, MF_OWNERDRAW, 0, "Item04");
AppendMenu(hMenuSub1, MF_OWNERDRAW, 0, "Item05");
AppendMenu(hMenu, MF_OWNERDRAW | MF_POPUP, (UINT)hMenuSub2, "SubMenu2");
AppendMenu(hMenu, MF_OWNERDRAW | MF_POPUP, (UINT)hMenuSub3, "SubMenu3");
MENUINFO menuInfo;
menuInfo.cbSize = sizeof(menuInfo);
menuInfo.fMask = MIM_BACKGROUND;
menuInfo.hbrBack = CreateSolidBrush(colorTheme.pink);
SetMenuInfo(hMenu, &menuInfo);
SetMenu(hMainWnd, hMenu);
ShowWindow(hMainWnd, nCmdShow);
while (GetMessage(&msg, NULL, NULL, NULL)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hDC = BeginPaint(hWnd, &ps);
HFONT hApplicationFont;
LOGFONT applicationFont;
applicationFont.lfHeight = 16;
applicationFont.lfWidth = 6;
applicationFont.lfEscapement = 0;
applicationFont.lfOrientation = 0;
applicationFont.lfWeight = FW_NORMAL;
applicationFont.lfItalic = FALSE;
applicationFont.lfUnderline = FALSE;
applicationFont.lfStrikeOut = FALSE;
applicationFont.lfCharSet = DEFAULT_CHARSET;
applicationFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
applicationFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
applicationFont.lfQuality = ANTIALIASED_QUALITY;
applicationFont.lfPitchAndFamily = DEFAULT_PITCH;
strcpy_s(applicationFont.lfFaceName, "Arial");
hApplicationFont = CreateFontIndirectA(&applicationFont);
SelectObject(hDC, hApplicationFont);
SelectObject(hDC, GetStockObject(DC_PEN));
SetDCPenColor(hDC, colorTheme.clientBorder);
SelectObject(hDC, GetStockObject(DC_BRUSH));
SetDCBrushColor(hDC, colorTheme.clientBackground);
RECT clientRect;
GetClientRect(hWnd, &clientRect);
Rectangle(hDC, 0, 0, clientRect.right, clientRect.bottom);
EndPaint(hWnd, &ps);
break;
}
case WM_MEASUREITEM:
{
LPMEASUREITEMSTRUCT itemStruct = (LPMEASUREITEMSTRUCT)lParam;
const char* str = (const char*)(itemStruct->itemData);
SIZE strSize;
HDC hDC = GetDC(hWnd);
GetTextExtentPoint32(hDC, str, lstrlen(str), &strSize);
itemStruct->itemWidth = strSize.cx;
itemStruct->itemHeight = 30;
ReleaseDC(hWnd, hDC);
return TRUE;
break;
}
case WM_DRAWITEM:
{
LPDRAWITEMSTRUCT itemStruct = (LPDRAWITEMSTRUCT)lParam;
HDC hDC = itemStruct->hDC;
SelectObject(hDC, GetStockObject(DC_PEN));
SetDCPenColor(hDC, colorTheme.itemBorder);
SelectObject(hDC, GetStockObject(DC_BRUSH));
SetDCBrushColor(hDC, colorTheme.itemBackground);
SetTextColor(hDC, colorTheme.text);
SetBkMode(hDC, TRANSPARENT);
Rectangle(hDC, itemStruct->rcItem.left,
itemStruct->rcItem.top,
itemStruct->rcItem.right,
itemStruct->rcItem.bottom + 1);
DrawText(hDC, (const char*)(itemStruct->itemData), -1, &(itemStruct->rcItem), DT_SINGLELINE | DT_CENTER | DT_VCENTER);
break;
}
case WM_DESTROY:
{
PostQuitMessage(NULL);
break;
}
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return NULL;
}
It seems to be part of the non-client area of the window. If that's the case then to paint there you need to handle WM_NCPAINT.
It is a single pixel line above the window's client area, so for example if I add the following code to your program I can paint it in red.
// ... in the WNDPROC
case WM_NCPAINT:
{
auto result = DefWindowProc(hWnd, WM_NCPAINT, wParam, lParam);
HDC hdc = GetWindowDC(hWnd);
RECT r = GetNonclientMenuBorderRect(hWnd);
HBRUSH red = CreateSolidBrush(RGB(255, 0, 0));
FillRect(hdc, &r, red);
DeleteObject(red);
ReleaseDC(hWnd, hdc);
return result;
}
// ... elsewhere
RECT MapRectFromClientToWndCoords(HWND hwnd, const RECT& r)
{
RECT wnd_coords = r;
// map to screen
MapWindowPoints(hwnd, NULL, reinterpret_cast<POINT*>(&wnd_coords), 2);
RECT scr_coords;
GetWindowRect(hwnd, &scr_coords);
// map to window coords by substracting the window coord origin in
// screen coords.
OffsetRect(&wnd_coords, -scr_coords.left, -scr_coords.top);
return wnd_coords;
}
RECT GetNonclientMenuBorderRect(HWND hwnd)
{
RECT r;
GetClientRect(hwnd, &r);
r = MapRectFromClientToWndCoords(hwnd, r);
int y = r.top - 1;
return {
r.left,
y,
r.right,
y+1
};
}
Now an issue with the above code is that it is over-painting the rectangle after the default non-client painting is done. In theory this could flicker; in practice I don't notice a flicker. If it did flicker, however, a safer way to do this would be to modify the WPARAM you pass to DefWindowProc(hWnd, WM_NCPAINT, ... ) such that it is the handle to a region that is the region passed to WM_NCPAINT minus the rectangle you want to paint. This doesnt seem necessary to me, for whatever reason.
If you are using themes / visual styles, which pretty much everything is nowadays, you can't override a lot of the menu styling without using a workaround like https://github.com/adzm/win32-custom-menubar-aero-theme which also uses the same approach to get rid of the white line. Note that you will need to handle this in WM_NCPAINT and WM_NCACTIVATE.

How draw caption in alt+tab switcher when paint custom caption(frame)?

I need to draw a custom caption bar, where I draw the window caption by myself.
HDC hdc = GetWindowDC(hwnd);
if (hdc && prepareTitleBarDC(getWidth(), 27)) {
SetWindowText(hwnd, _T(""));
DefWindowProc(hwnd, WM_NCPAINT, wParam, lParam);
m_titleBar->setSize(getWidth(), 27);
m_titleBar->setBkColor(SkColorSetARGB(0x00, 0x00, 0x00, 0x00));
m_titleBar->paintEvent(m_pTitleBarDC);
FnSkBitmap::SaveSkBitmap(m_pTitleBarDC->canvas(), L"e:\\titlebar.bmp");
HDC hdcPaint = CreateCompatibleDC(hdc);
HBITMAP hbm = CreateCompatibleBitmap(hdc, getWidth(), 27);
SelectObject(hdcPaint, hbm);
FnSkBitmap::DrawSkBitmap(m_pTitleBarDC->bitmap(), hdcPaint);
BLENDFUNCTION bfn = {0};
bfn.BlendOp = AC_SRC_OVER;
bfn.BlendFlags = 0;
bfn.SourceConstantAlpha = 255;
bfn.AlphaFormat = AC_SRC_ALPHA;
AlphaBlend(hdc, 0, 0, getWidth(), 27, hdcPaint, 0, 0, getWidth(), 27, bfn);
}
ReleaseDC(hwnd, hdc);
return 0;
And use AlphaBlend to mix the standard frame with myself, but if I use SetWindowText(_T("")), then the title in Alt+Tab switcher gone.
I try to handle WM_GETTEXT message and return the caption string, but failed. How could I draw the caption text by myself but still make the title in alt+tab switcher?
Since you are already drawing a "custom caption bar" there is no reason to have it actually draw using the actual window's text
there are two ways to accomplish this, one using the traditional DrawCaption from Win9x Win32Api, the other is using the more fresher "theme api"
here is an example that uses both:
#include <Windows.h>
#include <Uxtheme.h>
#include <vssym32.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
const LPCWSTR WINDOW_CLASS = L"Test Window Class";
const LPCWSTR WINDOW_CAPTION = L"This is my test window";
const LPCWSTR CUSTOM_CAPTION = L"Custom Caption Text";
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
WNDCLASSEX wndClassEx = {};
wndClassEx.lpszClassName = WINDOW_CLASS;
wndClassEx.hInstance = hInstance;
wndClassEx.lpfnWndProc = WindowProc;
wndClassEx.cbSize = sizeof(wndClassEx);
wndClassEx.hCursor = (HCURSOR) LoadImage(NULL, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR, 0, 0, LR_SHARED | LR_DEFAULTSIZE);
wndClassEx.style = CS_DBLCLKS | CS_DROPSHADOW;
ATOM registeredClass = RegisterClassEx(&wndClassEx);
HWND hwnd = CreateWindowEx(
0,
WINDOW_CLASS,
WINDOW_CAPTION,
WS_SYSMENU,
200, 200, 500, 300,
NULL, // parent
NULL, // menu
hInstance,
NULL // extra
);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, nCmdShow);
MSG msg = {};
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_LBUTTONDBLCLK:
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
// fill the window with a color
HBRUSH hbrush = CreateSolidBrush(RGB(33, 33, 33));
FillRect(hdc, &ps.rcPaint, hbrush);
DeleteObject(hbrush);
// get a drawing area
RECT rect = {};
GetClientRect(hwnd, &rect);
rect.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYEDGE) * 2;
// draw a simple win9x style caption (switch out the window text while drawing)
SetWindowText(hwnd, CUSTOM_CAPTION);
DrawCaption(hwnd, hdc, &rect, DC_GRADIENT | DC_TEXT | DC_ACTIVE | DC_ICON);
SetWindowText(hwnd, WINDOW_CAPTION);
// use theme framework
HTHEME htheme = OpenThemeData(hwnd, L"Window");
// move downwards and then use new APIs for size
rect.top += rect.bottom + 20;
rect.bottom = rect.top + GetThemeSysSize(htheme, SM_CYSIZE) + GetThemeSysSize(htheme, SM_CXPADDEDBORDER) * 2;
// draw the background
DrawThemeBackground(htheme, hdc, WP_CAPTION, CS_ACTIVE, &rect, &ps.rcPaint);
// load the caption font and save the old one
LOGFONTW captionfont = {};
GetThemeSysFont(htheme, TMT_CAPTIONFONT, &captionfont);
HFONT newfont = CreateFontIndirect(&captionfont);
HGDIOBJ oldfont = SelectObject(hdc, newfont);
// center the font and draw
rect.top += GetThemeSysSize(htheme, SM_CXPADDEDBORDER);
DrawThemeTextEx(htheme, hdc, WP_CAPTION, CS_ACTIVE, CUSTOM_CAPTION, -1, DT_CENTER, &rect, NULL);
// cleanup fonts
SelectObject(hdc, oldfont);
DeleteObject(newfont);
// adjust draw location, load icon and draw
rect.left += GetThemeSysSize(htheme, SM_CXPADDEDBORDER) * 2;
rect.top += GetThemeSysSize(htheme, SM_CXPADDEDBORDER);
HICON icon = (HICON) LoadImage(NULL, MAKEINTRESOURCE(IDI_APPLICATION), IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE);
DrawIconEx(hdc, rect.left, rect.top, icon, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0, NULL, DI_NORMAL);
// close theme
CloseThemeData(htheme);
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
the resulting window looks like:
You can see that the 2 "custom drawn" title bars display custom text, not the text on the window.
A quick glance at the code will tell you that attempting the theme window caption using a custom routine is a lot more difficult than the legacy. The trade off of course is that it gives you way more control. You'll also take note that I switch out the window text to make it display what I want when using the legacy method. Additionally you need to remember that the legacy method takes its queues on how to draw itself from the styles associated with the window, if your window style has no icon, it will not draw one even if you specify it...
Either of these techniques will accomplish your goal. If I switched this code around not to draw multiple title bars and get rid of the default one created by the window style the result would look like:
you can see here how the task switch still displays the actual window text, and my "custom" caption bar looks like the real deal...
good luck, i hope this helps -ck
on a side note: i am running Windows8 and am not sure why the caption drawing routines are ignoring my theme... perhaps i forgot a directive

How to draw image on a window?

I have created a window with createwindow() api using VS2005 in C++ on Windows Vista
My requirement is to draw an image (of any format) on that window. I am not using any MFC in this application.
not exactly sure what is your problem: draw a bitmap on the form, or you would like know how to work with various image formats, or both. Anyways below is an example of how you could load a bitmap and draw it on the form:
HBITMAP hBitmap = NULL;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
switch (message)
{
<...>
case WM_CREATE:
hBitmap = (HBITMAP)LoadImage(hInst, L"c:\\test.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
break;
case WM_PAINT:
PAINTSTRUCT ps;
HDC hdc;
BITMAP bitmap;
HDC hdcMem;
HGDIOBJ oldBitmap;
hdc = BeginPaint(hWnd, &ps);
hdcMem = CreateCompatibleDC(hdc);
oldBitmap = SelectObject(hdcMem, hBitmap);
GetObject(hBitmap, sizeof(bitmap), &bitmap);
BitBlt(hdc, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, oldBitmap);
DeleteDC(hdcMem);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
DeleteObject(hBitmap);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
LoadImage loads an icon, cursor, animated cursor, or bitmap. Details here
For working with various images formats you can use Windows Imaging Component (see IWICBitmapDecoder) or code from here Loading JPEG and GIF pictures or 3rd party tools like FreeImage or LeadTools
hope this helps, regards
void LoadScreen(HWND hWnd) {
RECT rect;
HDC hdc = GetDC(hWnd);
HBRUSH brush = CreatePatternBrush((HBITMAP)LoadImage(NULL, L"file.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE));
GetWindowRect(hWnd, &rect);
FillRect(hdc, &rect, brush);
DeleteObject(brush);
ReleaseDC(hWnd, hdc);
}
#include <windows.h>
#include <string.h>
HBITMAP hBitmap, hOldBitmap;
HDC hdc, hdcMem;
BITMAP bm;
HINSTANCE hI;
PAINTSTRUCT ps;
RECT rect;
RECT rc;
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
hBitmap = (HBITMAP)LoadImage(hI, "1.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
GetObject(hBitmap, sizeof(BITMAP), &bm);
hdc = GetDC(hWnd);
hdcMem = CreateCompatibleDC(hdc);
hOldBitmap = SelectBitmap(hdcMem, hBitmap);
ReleaseDC(hWnd, hdc);
return 0;
case WM_LBUTTONDOWN:
//for dragging not only by the title, but also by any part of the window
ReleaseCapture();
SendMessage(hWnd, 0xA1, 2, 0);
break;
case WM_PAINT:
hdc=BeginPaint(hWnd,&ps);
//overlay image with stretching to fit the window
GetClientRect(hWnd,&rect);
SetStretchBltMode(hdc, STRETCH_HALFTONE);
StretchBlt(hdc,0,0,rect.right,rect.bottom,
hdcMem,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
EndPaint(hWnd,&ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
DeleteDC(hdcMem);
DeleteObject(hBitmap);
DeleteObject(hOldBitmap);
break;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPInst, LPSTR lpCmdLine, int nCmdShow)
{
//copying a pointer to a running application instance (module)
hI=hInstance;
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProcedure;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) GetStockObject(LTGRAY_BRUSH);
wc.lpszClassName = "test_class";
wc.lpszMenuName = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
RegisterClass(&wc);
HWND hWnd = CreateWindow(wc.lpszClassName, "Image Window",
//window with title (overlapping window)
WS_OVERLAPPEDWINDOW,
//window without title
//WS_VISIBLE | WS_POPUP | WS_SYSMENU | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT, 500, 500, NULL, NULL, hInstance, NULL);
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
MSG msg;
while(GetMessage (&msg, NULL, 0, 0))
{
DispatchMessage (&msg);
TranslateMessage (&msg);
}
UnregisterClass(wc.lpszClassName, hInstance);
return (int) msg.wParam;
}

Resources