I have some problems with making static controls rounded. I can't understand why SetWindowRgn doesn't work for a static control here. Also I've tried SelectClipRgn and it works. But nevertheless why SetWindowRgn doesn't? The Microsoft documentation states that
The system does not display any portion of a window that lies outside
of the window region.
The control must be rounded and clipped according to the documentation. But it is not. Here's my example of the problem:
#include <windows.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
HWND hwnd = CreateWindowEx(
0, // Optional window styles.
CLASS_NAME, // Window class
L"Learn to Program Windows", // Window text
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, // Window style
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
if (hwnd == NULL)
{
return 0;
}
HRGN hrgnMain = CreateRoundRectRgn(0, 0, 200, 200, 5, 5);
int res = SetWindowRgn(hwnd, hrgnMain, TRUE);
ShowWindow(hwnd, nCmdShow);
HWND hControl = CreateWindow(L"Static", L"hello, world", WS_VISIBLE | WS_CHILD | SS_NOTIFY | SS_LEFTNOWORDWRAP,
20, 20, 40, 40, hwnd, NULL, hInstance, NULL);
HRGN hrgnControl = CreateRoundRectRgn(0, 0, 10, 10, 5, 5);
res = SetWindowRgn(hControl, hrgnControl, TRUE);
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_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
Some builtin controls use CS_PARENTDC class style.
CS_PARENTDC sets the clipping region of the child window to that of the parent window. This conflicts with SetWindowRgn which wants to install custom region. Depending how your window is refreshed you could get different combinations of custom region working or not. For example if you resize parent window you can get your control refreshed partially with region set and partially without region.
Parent Display Device Contexts states that:
The system ignores the CS_PARENTDC style if the parent window uses a
private or class device context, if the parent window clips its child
windows, or if the child window clips its child windows or sibling
windows.
But it looks that setting only WS_CLIPCHILDREN for parent windows is not enough. Adding WS_CLIPSIBLINGS or WS_CLIPCHILDREN flags in control styles (even if you have only one child) triggers desired behavior.
HWND hControl = CreateWindow(
L"Static",
L"hello, world",
WS_CLIPSIBLINGS | WS_VISIBLE | WS_CHILD | SS_NOTIFY | SS_LEFTNOWORDWRAP,
20, 20, 40, 40,
hwnd,
NULL,
hInstance,
NULL);
Your code without WS_CLIPSIBLINGS
And with WS_CLIPSIBLINGS
Alternatively the CS_PARENT style could be removed by using GetClassLongPtr and SetClassLongPtr. Because CS_PARENT is used only to reuse clipping region it shouldn't have any other unexpected effects.
SetClassLongPtr(
hControl,
GCL_STYLE,
GetClassLongPtr( hControl, GCL_STYLE ) & ~CS_PARENTDC );
Related
I am new to using international languages in my win32 program in C++. I have a simple window created with an edit field inside. I want to set a chinese hardcoded text into the edit field. I am using SetWindowText but the output has only question marks and | character. What am I missing? My code file is pasted below. I have tried WM_SETTEXT but no luck.
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
#include <strsafe.h>
#include <iostream>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
// Create the window.
HWND hwnd = CreateWindowEx(
0, // Optional window styles.
CLASS_NAME, // Window class
L"Learn to Program Windows", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
if (hwnd == NULL)
{
return 0;
}
HWND edit = CreateWindowEx(0, L"Edit", L"", WS_CHILD | WS_VISIBLE | WS_BORDER, 0, 0, 200, 50, hwnd, NULL, hInstance, NULL);
SetWindowTextW(edit, L"銷售回扣");
//SendMessage(edit, WM_SETTEXT, 0, (LPARAM)(L"銷售回扣"));
ShowWindow(hwnd, nCmdShow);
// Run the message loop.
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_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
// All painting occurs here, between BeginPaint and EndPaint.
FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1));
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
I am writing my first Win32 app in C++ and I am trying to create 3 windows between which to redirect based on what buttons the user clicks on. I initialised the windows (window1,window2,window3) as children of the main window hwnd and only set window1 as visible. window1 also has two buttons, each of which is supposed to direct either to window2 or window3.
I tried to hide window1 and show which window I want to switch to using the ShowWindow() function. However, it is not working (clicking the buttons does nothing). Could you help me understand why?
On another piece of code I had before, where I had not created window1, and the buttons and the other two windows were just children of hwnd, pressing the button did show the right window, but the button remained there, even if it did not belong on that window.
Also, is there a more efficient way of switching between windows (without deleting and creating them again and again?
Thanks!!!
EDIT: I managed to solve my problem. It arose from the fact that I had declared windows 1,2 and 3 as static. By declaring them under the same class as hwnd, I was able to process the messages from the buttons under the main WindowProcedure(). Since my program is gonna be quite simple, I do not need to create a different procedure for the new windows, but thanks to the comments, now I also know how to do that!
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
window1 = CreateWindow("STATIC","Window 1",WS_VISIBLE|WS_BORDER|WS_CHILD,0,0,600,600,hwnd,NULL,NULL,NULL);
window2 = CreateWindow("STATIC","Window 2",WS_BORDER|WS_CHILD,0,0,600,600,hwnd,NULL,NULL,NULL);
button2 = CreateWindow(
"BUTTON",
"SECOND WINDOW",
WS_CHILD | WS_VISIBLE | WS_BORDER,
350, 480,
200, 20,
window1, (HMENU) 2, NULL, NULL);
window3 = CreateWindow("STATIC","Window 3",WS_BORDER|WS_CHILD,0,0,600,600,hwnd,NULL,NULL,NULL);
button3 = CreateWindow(
"BUTTON",
"THIRD WINDOW",
WS_CHILD | WS_VISIBLE | WS_BORDER,
50, 480,
200, 20,
window1, (HMENU) 3, NULL, NULL);
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case 2:
ShowWindow(window1,SW_HIDE);
ShowWindow(window2,SW_SHOW);
break;
case 3:
ShowWindow(window1,SW_HIDE);
ShowWindow(window3,SW_SHOW);
break;
}
break;
case WM_DESTROY:
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
break;
default: /* for messages that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
First, create a new window1 as in the steps of creating the main form.
Then create a windowprocessforwindow1 for window1, process the WM_COMMAND message in this function.
Here is the sample:
#include <Windows.h>
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK windowprocessforwindow1(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
static HWND window1, window2, button2, window3, button3;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("hello windows");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WindowProcedure;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);
}
hwnd = CreateWindow(szAppName,
TEXT("the hello program"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while (GetMessageW(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
static HINSTANCE hInstance;
static WNDCLASSEX win1;
case WM_CREATE:
hInstance = (HINSTANCE)::GetWindowLong(hwnd, GWL_HINSTANCE);
win1.hInstance = hInstance;
win1.lpszClassName = L"Window 1";
win1.lpfnWndProc = (WNDPROC)windowprocessforwindow1; /* This function is called by windows */
win1.style = CS_DBLCLKS; /* Catch double-clicks */
win1.cbSize = sizeof(WNDCLASSEX);
win1.hIcon = LoadIcon(NULL, IDI_APPLICATION);
win1.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
win1.hCursor = LoadCursor(NULL, IDC_ARROW);
win1.lpszMenuName = NULL; /* No menu */
win1.cbClsExtra = 0; /* No extra bytes after the window class */
win1.cbWndExtra = 0; /* structure or the window instance */
win1.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
if (!RegisterClassEx(&win1))
return 0;
window1 = CreateWindowEx(
0, /* Extended possibilites for variation */
L"Window 1", /* Classname */
L"Window 1", /* Title Text */
WS_VISIBLE | WS_BORDER | WS_CHILD, /* default window */
0, /* Windows decides the position */
0, /* where the window ends up on the screen */
600, /* The programs width */
600, /* and height in pixels */
hwnd, /* The window is a child-window to desktop */
NULL, /* No menu */
hInstance, /* Program Instance handler */
NULL /* No Window Creation data */
);
window2 = CreateWindow(L"STATIC", L"Window 2", WS_BORDER | WS_CHILD, 0, 0, 600, 600, hwnd, NULL, NULL, NULL);
button2 = CreateWindow(
L"BUTTON",
L"SECOND WINDOW",
WS_CHILD | WS_VISIBLE | WS_BORDER,
350, 480,
200, 20,
window1, (HMENU)2, NULL, NULL);
window3 = CreateWindow(L"STATIC", L"Window 3", WS_BORDER | WS_CHILD, 0, 0, 600, 600, hwnd, NULL, NULL, NULL);
button3 = CreateWindow(
L"BUTTON",
L"THIRD WINDOW",
WS_CHILD | WS_VISIBLE | WS_BORDER,
50, 480,
200, 20,
window1, (HMENU)3, NULL, NULL);
ShowWindow(window1, SW_SHOW);
break;
case WM_DESTROY:
PostQuitMessage(0); /* send a WM_QUIT to the message queue */
break;
default: /* for messages that we don't deal with */
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
LRESULT CALLBACK windowprocessforwindow1(HWND handleforwindow1, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_COMMAND:
{
switch (wParam) {
case 2:
ShowWindow(window1, SW_HIDE);
ShowWindow(window2, SW_SHOW);
break;
case 3:
ShowWindow(window1, SW_HIDE);
ShowWindow(window3, SW_SHOW);
break;
}
}
return 0;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(handleforwindow1, msg, wParam, lParam);
}
return 0;
}
I am trying to create a listview in C++ with the win32 api, however the code supplied on mdsn is giving me an error.
HWND CreateListView (HWND hwndParent)
{
INITCOMMONCONTROLSEX icex; // Structure for control initialization.
icex.dwICC = ICC_LISTVIEW_CLASSES;
InitCommonControlsEx(&icex);
RECT rcClient; // The parent window's client area.
GetClientRect (hwndParent, &rcClient);
// Create the list-view window in report view with label editing enabled.
HWND hWndListView = CreateWindow(WC_LISTVIEW, //ERROR red line under create window
L"",
WS_CHILD | LVS_REPORT | LVS_EDITLABELS,
0, 0,
rcClient.right - rcClient.left,
rcClient.bottom - rcClient.top,
hwndParent,
(HMENU)IDM_CODE_SAMPLES, //ERROR IDM CODE SAMPLES undefined
g_hInst, //ERROR
NULL);
return (hWndListView);
}
This example is strait from mdsn and I have no idea why it is not working. I am getting IDM_CODE_SAMPLES Undefined, and something wrong with createwindow. Please help me to get this working it would be really helpful.
IDM_CODE_SAMPLES is the ID you want to assign to your control. You can either define the symbol to a numeric value, or use the numeric value directly (choose 100, for example). The ID is useful if you want to reference a particular control, although its HWND is equally useful as an ID.
g_hInst is presumably a global variable of type HMODULE, initialized from WinMain. If you don't want to use the global variable, you can call GetModuleHandle(nullptr) in its place, provided that you are compiling an .exe as opposed to a .dll.
You'll get a lot of helpful information when working through Intro to Win32 programming in C++.
I am now getting an error (1 unresolved externals)
We can find from InitCommonControlsEx function.
Ensures that the common control DLL (Comctl32.dll) is loaded, and
registers specific common control classes from the DLL.
Add:
#include <commctrl.h>
#pragma comment(lib,"Comctl32.lib")
Minimal code example:
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
#include <commctrl.h>
#pragma comment(lib,"Comctl32.lib")
#define IDM_CODE_SAMPLES 101
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
HWND CreateListView(HWND hwndParent);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
// Create the window.
HWND hwnd = CreateWindowEx(
0, // Optional window styles.
CLASS_NAME, // Window class
L"Learn to Program Windows", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
CreateListView(hwnd);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, nCmdShow);
// Run the message loop.
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_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
HWND CreateListView(HWND hwndParent)
{
INITCOMMONCONTROLSEX icex; // Structure for control initialization.
icex.dwICC = ICC_LISTVIEW_CLASSES;
InitCommonControlsEx(&icex);
RECT rcClient; // The parent window's client area.
GetClientRect(hwndParent, &rcClient);
// Create the list-view window in report view with label editing enabled.
HWND hWndListView = CreateWindow(WC_LISTVIEW, //ERROR red line under create window
L"",
WS_CHILD | LVS_REPORT | LVS_EDITLABELS,
0, 0,
rcClient.right - rcClient.left,
rcClient.bottom - rcClient.top,
hwndParent,
(HMENU)IDM_CODE_SAMPLES, //ERROR IDM CODE SAMPLES undefined
GetModuleHandle(nullptr), //ERROR
NULL);
return (hWndListView);
}
Just in case someone else is having issues around SysListView32:
#include <Ole2.h>
OleInitialize(NULL);
#include <commctrl.h>
#pragma comment(lib, "Shlwapi.lib")
#pragma comment(lib, "comctl32.lib")
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwICC = ICC_LISTVIEW_CLASSES;
InitCtrls.dwSize = sizeof(INITCOMMONCONTROLSEX);
BOOL bRet = InitCommonControlsEx(&InitCtrls);
...
For reference: fully working example with bells and whistles: https://github.com/jjYBdx4IL/Win32-List-View
I have some problems with making static controls rounded. I can't understand why SetWindowRgn doesn't work for a static control here. Also I've tried SelectClipRgn and it works. But nevertheless why SetWindowRgn doesn't? The Microsoft documentation states that
The system does not display any portion of a window that lies outside
of the window region.
The control must be rounded and clipped according to the documentation. But it is not. Here's my example of the problem:
#include <windows.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
HWND hwnd = CreateWindowEx(
0, // Optional window styles.
CLASS_NAME, // Window class
L"Learn to Program Windows", // Window text
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, // Window style
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
if (hwnd == NULL)
{
return 0;
}
HRGN hrgnMain = CreateRoundRectRgn(0, 0, 200, 200, 5, 5);
int res = SetWindowRgn(hwnd, hrgnMain, TRUE);
ShowWindow(hwnd, nCmdShow);
HWND hControl = CreateWindow(L"Static", L"hello, world", WS_VISIBLE | WS_CHILD | SS_NOTIFY | SS_LEFTNOWORDWRAP,
20, 20, 40, 40, hwnd, NULL, hInstance, NULL);
HRGN hrgnControl = CreateRoundRectRgn(0, 0, 10, 10, 5, 5);
res = SetWindowRgn(hControl, hrgnControl, TRUE);
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_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
Some builtin controls use CS_PARENTDC class style.
CS_PARENTDC sets the clipping region of the child window to that of the parent window. This conflicts with SetWindowRgn which wants to install custom region. Depending how your window is refreshed you could get different combinations of custom region working or not. For example if you resize parent window you can get your control refreshed partially with region set and partially without region.
Parent Display Device Contexts states that:
The system ignores the CS_PARENTDC style if the parent window uses a
private or class device context, if the parent window clips its child
windows, or if the child window clips its child windows or sibling
windows.
But it looks that setting only WS_CLIPCHILDREN for parent windows is not enough. Adding WS_CLIPSIBLINGS or WS_CLIPCHILDREN flags in control styles (even if you have only one child) triggers desired behavior.
HWND hControl = CreateWindow(
L"Static",
L"hello, world",
WS_CLIPSIBLINGS | WS_VISIBLE | WS_CHILD | SS_NOTIFY | SS_LEFTNOWORDWRAP,
20, 20, 40, 40,
hwnd,
NULL,
hInstance,
NULL);
Your code without WS_CLIPSIBLINGS
And with WS_CLIPSIBLINGS
Alternatively the CS_PARENT style could be removed by using GetClassLongPtr and SetClassLongPtr. Because CS_PARENT is used only to reuse clipping region it shouldn't have any other unexpected effects.
SetClassLongPtr(
hControl,
GCL_STYLE,
GetClassLongPtr( hControl, GCL_STYLE ) & ~CS_PARENTDC );
How I can change the background image of a window at runtime in WIN32?
I have created the window using CreateWindow(). Then I have a LoadImage Button which opens a model dialog box (open file dialog)... Now I want to use the file name returned by this dialog box as the image of the window.
There is no native concept for the window background, you have to manually paint your image, usually in the WM_ERASEBKGND message. If you are using MFC you can check this article: http://www.codeproject.com/KB/graphics/picturewindow.aspx
A piece of sample code of what CoreyStup explains, in the window callback:
switch (message)
{
case WM_CREATE:
{
HBITMAP hImage = (HBITMAP)LoadImage(NULL, L"guibg.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
HWND hImageView = CreateWindowEx(NULL, L"STATIC", NULL, SS_BITMAP | WS_VISIBLE | WS_CHILD, 0, 00, 500, 600, hWnd, (HMENU)IMAGE_VIEW, GetModuleHandle(NULL), NULL);
SendMessage(hImageView, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hImage);
...
Credits also to fritzone who answered this on this similar thread: How to add picture box in win32 API using visual c++
NOTE: Use bitmaps generated by paint, otherwise LoadImage may return NULL without an error and the image will be invisible.
compile the code below.
write your file name in textbox and press change background.
i use mingw 4.7.
you can only use .bmp images, if you want to use other image you have to use GdiPluse.
#include <windows.h>
//variables
HWND hwnd01, label01;
HBITMAP hBitmap01 = NULL;
//functions
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{
MSG msg ;
WNDCLASS wc = {0};
wc.lpszClassName = TEXT( "GUI01" );
wc.hInstance = hInstance ;
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.lpfnWndProc = WndProc ;
wc.hCursor = LoadCursor(0, IDC_ARROW);
RegisterClass(&wc);
hwnd01 = CreateWindow( wc.lpszClassName, TEXT("GUI01 Headline"),
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
150, 150, 330, 150, 0, 0, hInstance, 0);
while( GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch(msg)
{
case WM_CREATE:
{
CreateWindow(TEXT("button"), TEXT("Change Background"),
WS_VISIBLE | WS_CHILD ,
20, 50, 140, 25,
hwnd, (HMENU) 1, NULL, NULL);
CreateWindow(TEXT("button"), TEXT("Quit"),
WS_VISIBLE | WS_CHILD ,
190, 50, 80, 25,
hwnd, (HMENU) 2, NULL, NULL);
label01 = CreateWindow(TEXT("Edit"), TEXT("Label"),
WS_VISIBLE | WS_CHILD,
20, 10, 280, 25,
hwnd, (HMENU) 3, NULL, NULL);
break;
}
case WM_COMMAND:
{
if (LOWORD(wParam) == 1) {
TCHAR* string01 = new TCHAR[300];
GetWindowText(label01, string01, 300);
hBitmap01 = (HBITMAP)LoadImage(NULL, string01, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
if (hBitmap01==NULL)
MessageBox(NULL, "Error Loading Image.", "ERROR", MB_ICONWARNING | MB_DEFBUTTON2);
else
InvalidateRect(hwnd01, NULL, TRUE);
}
if (LOWORD(wParam) == 2) {
PostQuitMessage(0);
}
break;
}
case WM_PAINT:
{
PAINTSTRUCT ps01;
HDC hdc01;
BITMAP bitmap01;
HDC hdcMem01;
HGDIOBJ oldBitmap01;
hdc01 = BeginPaint(hwnd01, &ps01);
hdcMem01 = CreateCompatibleDC(hdc01);
oldBitmap01 = SelectObject(hdcMem01, hBitmap01);
GetObject(hBitmap01, sizeof(bitmap01), &bitmap01);
BitBlt(hdc01, 0, 0, bitmap01.bmWidth, bitmap01.bmHeight, hdcMem01, 0, 0, SRCCOPY);
SelectObject(hdcMem01, oldBitmap01);
DeleteDC(hdcMem01);
EndPaint(hwnd01, &ps01);
break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
A static control can have a background image (although its limited to bitmaps). You can put a child static control inside of your window (sized edge to edge) and set it as the background.
If you want fancy image handling like transparency, you'll need to do that manually.