I'm trying to learn how to create a window in win 32. This is as far as I have got with it. The problem I'm facing is I'm unable to create a window that can be resized by the user. I'm hoping that someone could help me solve this newbie problem.
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
std::string msg = "";
UINT width = 0;
UINT height = 0;
switch(uMsg)
{
case WM_SIZE:
width = LOWORD(lParam);
height = HIWORD(lParam);
if(width<(height*600)/800) SetWindowPos(hWnd, NULL, 0, 0, width, height, SWP_NOMOVE|SWPNOZORDER);
return true;
case WM_SIZING:
width = LOWORD(lParam);
height = HIWORD(lParam);
if(width<(height*600)/800) SetWindowPos(hWnd, NULL, 0, 0, width, height, SWP_NOMOVE|SWPNOZORDER);
return true;
case WM_DESTROY:
PostQuitMessage(0);
return true;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR lpCmdLine, INT nCmdShow)
{
WNDCLASSEX wnd = {0};
wnd.lpszClassName = "WindowLearn";
wnd.hInstance = hInstance;
wnd.lpfnWndProc = windowProc;
wnd.cbSize = sizeof(WNDCLASSEX);
wnd.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wnd);
HWND hWnd = CreateWindowEx(NULL, "WindowLearn", "WindowLearnChild", WS_THICKFRAME | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, 0, 0, 800, 600, NULL, NULL, hInstance, NULL);
ShowWindow(hWnd, nCmdShow);
MSG msg = {0};
float pTime = 0.0f;
BOOL result;
while(msg.message != WM_QUIT)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Window gets created OK, but with this when I try to resize the window the window gets stuck to the mouse.
It appears that you want to to idle processing, meaning having some tasks done for your directX application when no event are present in the event loop.
There are 2 different ways of doing that:
dedicate a separate thread for background processing. It adds the complexity of multiprocessing, but allows to do all the processing as a single piece of code, and let the system affect time slices to the event loop and the background processing.
use a modified event loop that does chunks of background processing when no event are present. PeekMessage is the key here:
...
MSG msg = {0};
for (;;)
{
if (PeekMessage(&msg, NULL, 0, 0, 0, 0) {
if (! GetMessage(&msg, NULL, 0, 0, 0)) break; // msg is WM_QUIT
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else {
// do some idle processing for a short time
// no event will be processing during that
...
}
}
The nice point is that you do not need any multi-threading, but you have to explicitely split you backgroung processing in short time slices.
Related
So basically I have this program that makes a transparent overlay for a game so I can make a kill counter. However, when I click on the game with the overlay on, nothing happens. I managed to make it so when you click on it then it sends a message to the game telling it to shoot, however, when I tried the same for moving my characters head it was just laggy and snappy. When I would move my head quickly, my cursor would also fly out of the game window. How can I fix this so when I play the game it would be like its not even there.
I have tried sending the message and setting the window active AND using setcapture. However, none of these worked. I have tried looking at other places but they didn't work either.
/* This is my while(true) loop: */
while (TRUE)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
{
break;
}
TranslateMessage(&msg); // translates virtual-key messages into character messages
DispatchMessage(&msg); // dispatches a message to WindowProc
}
if (gameProcId == 0)
{
gameProcId = GetProcId(L"ac_client.exe");
}
if (gameWnd == NULL)
{
gameWnd = FindWindow(NULL, L"AssaultCube");
}
if ((gameProc == NULL) && (gameProcId != 0))
{
gameProc = OpenProcess(PROCESS_VM_READ, false, gameProcId); // opens an existing local process and returns a handle to it
}
if (gameProc != NULL)
{
if ((!init_ok) || ((loops % 20) == 0))
{
RECT client_rect;
#pragma warning (suppress: 6387)
GetClientRect(gameWnd, &client_rect); // gets a windows coordinates, upper-left corner is (0,0)
w_res.X = client_rect.right;
w_res.Y = client_rect.bottom;
RECT bounding_rect;
#pragma warning (suppress: 6387)
GetWindowRect(gameWnd, &bounding_rect); // gets dimensions of a window
if (!init_ok)
{
if ((w_pos.X != bounding_rect.left) || (w_pos.Y != bounding_rect.top))
{
MoveWindow(hWnd, bounding_rect.left, bounding_rect.top,
client_rect.right, client_rect.bottom, false);
w_pos.X = bounding_rect.left;
w_pos.Y = bounding_rect.top;
}
//SetCursorPos(w_pos.X * 4, w_pos.Y * 4);
//ClipCursor(&gameRect);
}
else
{
if ((bounding_rect.left == 0) && (bounding_rect.top == 0))
{
MoveWindow(hWnd, bounding_rect.left, bounding_rect.top, // changes both the position and dimension of a window
client_rect.right, client_rect.bottom, false);
}
MoveWindow(hWnd, bounding_rect.left, bounding_rect.top, client_rect.right,
client_rect.bottom, false);
}
init_ok = true;
}
}
if (loops % 10 == 0)
{
if (FindWindow(NULL, L"AssaultCube") == NULL)
{
SendMessage(hWnd, WM_CLOSE, NULL, NULL); // calls WindowProc() and sends the message to a window
}
}
loops++;
if (loops > 100) loops = 0;
Render();
}
}
/* This is my WindowProc() function: */
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}break;
case WM_LBUTTONDOWN:
{
PostMessage(gameWnd, message, wParam, lParam);
return 0;
}
case WM_MOUSEMOVE:
{
SendMessage(gameWnd, message, wParam, lParam);
return 0;
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
You didn't post enough code to attempt to solve this problem, we don't see your call to CreateWindowEx().
Here is a working solution for a win32 overlay:
#include <iostream>
#include <windows.h>
using namespace std;
//global forward declerations
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void cleanUpObjects(HPEN pen);
int CALLBACK WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
RECT overlayWindowRect;
RECT gameWindowRect;
HWND gameWindowHandle;
gameWindowHandle = FindWindowA(0, "AssaultCube");
GetWindowRect(gameWindowHandle, &gameWindowRect);
WNDCLASSEX w;
w.cbSize = sizeof(WNDCLASSEX);
w.style = CS_HREDRAW | CS_VREDRAW;
w.lpfnWndProc = WndProc;
w.cbClsExtra = 0;
w.cbWndExtra = 0;
w.hInstance = hInstance;
w.hIcon = NULL;
w.hCursor = NULL;
w.hbrBackground = (HBRUSH)0;
w.lpszMenuName = NULL;
w.lpszClassName = "ClassName";
w.hIconSm = NULL;
if (!RegisterClassEx(&w))
{
MessageBox(NULL, "Could not Register Class", "Window Title", NULL);
return -1;
}
HWND hWnd = CreateWindowEx(WS_EX_TOPMOST | WS_EX_LAYERED | WS_EX_TRANSPARENT, "ClassName", "Window",
WS_CAPTION,
gameWindowRect.left, //x
gameWindowRect.top, // y
gameWindowRect.right - gameWindowRect.left, // width
gameWindowRect.bottom - gameWindowRect.top, // height
NULL, NULL,
hInstance, NULL);
if (!hWnd)
{
MessageBox(NULL, "Call to create window failed", "Win32 Guided tour", NULL);
return -1;
}
else
{
GetWindowRect(hWnd, &overlayWindowRect);
}
// Remove Borders around window
SetWindowLong(hWnd, GWL_STYLE, GetWindowLong(hWnd, GWL_STYLE) & ~(WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_BORDER));
SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) & ~(WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE));
SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
// Make the Background Transparent
SetLayeredWindowAttributes(hWnd, RGB(255, 255, 255), 255, LWA_COLORKEY); // Replaces color white with transparancey
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
HDC myHDC = GetDC(hWnd);
// Drawing Stuff
HPEN myPen = CreatePen(PS_SOLID, 2, RGB(255, 0, 0));
HPEN originalPen;
originalPen = (HPEN)SelectObject(myHDC, myPen);
//main loop waits for messages
MSG msg;
while (true)
{
//peekmessage allows for program to do multiple things at once. faster than getmessage()
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
// if msg is quit, quit
if (msg.message == WM_QUIT)
break;
}
else
{
Rectangle(myHDC, 200, 200, 300, 400);
ZeroMemory(&gameWindowRect, sizeof(gameWindowRect)); //clear out the struct
GetWindowRect(gameWindowHandle, &gameWindowRect); // retrieves the games xy and height width and stores in gamewindowrect
if (gameWindowRect.right != overlayWindowRect.right) // checks if the x coordinates are the same
{
ZeroMemory(&gameWindowRect, sizeof(gameWindowRect)); // clear out struct once again
GetWindowRect(gameWindowHandle, &gameWindowRect); // get the dimensions of the game window again
MoveWindow(hWnd, gameWindowRect.left, gameWindowRect.top, gameWindowRect.right - gameWindowRect.left, gameWindowRect.bottom - gameWindowRect.top, TRUE);
// moves window to specific spot
}
}
Sleep(5);
}
cleanUpObjects(myPen);
cleanUpObjects(originalPen);
return msg.wParam;
}
LRESULT CALLBACK WndProc(
HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
PAINTSTRUCT ps;
HDC hdc;
switch (uMsg)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
DestroyWindow(hWnd);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
break;
}
return 0;
}
//cleans up objects
void cleanUpObjects(HPEN pen)
{
DeleteObject(pen);
}
Desktop Window Manager Uses A Ton Of CPU When Drawing DX9 Window.
I'm Not Sure Why It Is Using So Much CPU
https://imgur.com/a/Bz7AVro
LRESULT CALLBACK WinProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam){
Sleep(12);
switch (Message){
case WM_PAINT:
Render();
break;
case WM_CREATE:
DwmExtendFrameIntoClientArea(hWnd, &Margin);
break;
case WM_DESTROY:
PostQuitMessage(1);
return 0;
default:
return DefWindowProc(hWnd, Message, wParam, lParam);
break;
}
return 0;
}
ref class CMAIN {
public:
void StartIt() { Main(); }
};
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hSecInstance, LPSTR nCmdLine, INT nCmdShow){
Thread^ main;
CMAIN^ cMain = gcnew CMAIN();
main = gcnew Thread(gcnew ThreadStart(cMain, &CMAIN::StartIt));
main->Name = "main";
main->Start();
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)SetWindowToTarget, 0, 0, 0);
WNDCLASSEX wClass;
wClass.cbClsExtra = NULL;
wClass.cbSize = sizeof(WNDCLASSEX);
wClass.cbWndExtra = NULL;
wClass.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(0, 0, 0));
wClass.hCursor = LoadCursor(0, IDC_ARROW);
wClass.hIcon = LoadIcon(0, IDI_APPLICATION);
wClass.hIconSm = LoadIcon(0, IDI_APPLICATION);
wClass.hInstance = hInstance;
wClass.lpfnWndProc = WinProc;
wClass.lpszClassName = lWindowName;
wClass.lpszMenuName = lWindowName;
wClass.style = CS_VREDRAW | CS_HREDRAW;
if(!RegisterClassEx(&wClass))
exit(1);
tWnd = FindWindow(0, tWindowName);
if (tWnd){
GetWindowRect(tWnd, &tSize);
Width = tSize.right - tSize.left;
Height = tSize.bottom - tSize.top;
hWnd = CreateWindowEx(WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_LAYERED, lWindowName, lWindowName, WS_POPUP, 1, 1, Width, Height, 0, 0, 0, 0);
SetLayeredWindowAttributes(hWnd, 0, 1.0f, LWA_ALPHA);
SetLayeredWindowAttributes(hWnd, 0, RGB(0, 0, 0), LWA_COLORKEY);
ShowWindow( hWnd, SW_SHOW);
}
DirectXInit(hWnd);
while (!directXExit){
Sleep(12);
if(PeekMessage(&Message, hWnd, 0, 0, PM_REMOVE)){
DispatchMessage(&Message);
TranslateMessage(&Message);
}
}
return 0;
}
void SetWindowToTarget(){
while(true){
tWnd = FindWindow(0, tWindowName);
if (tWnd){
GetWindowRect(tWnd, &tSize);
Width = tSize.right - tSize.left;
Height = tSize.bottom - tSize.top;
DWORD dwStyle = GetWindowLong(tWnd, GWL_STYLE);
if(dwStyle & WS_BORDER){
tSize.top += 23;
Height -= 23;
}
MoveWindow(hWnd, tSize.left, tSize.top, Width, Height, true);
}
Sleep(1500);
}
}
It would be useful to get some more information around what you're trying to do, and it's also hard to see exactly what could be going on with the WM_PAINT handler in your code (since you call a function called Render but don't provide that code). But at first glance I think there's at least one thing that's going to force high CPU usage, and that's your message loop. You're basically spinning in that loop due to calling PeekMessage, with a call to Sleep(12) which will basically give you a ~80fps update on that window; since you're using the DWM composition code (DwmExtendFrameIntoClient) my guess is that you're triggering a 80Hz update in DWM because of that. If you're rendering something in realtime in that loop, then that's all to be expected and not avoidable (unless you put your rendering loop on a separate thread). But if you're just responding to WM_PAINT messages then you'd be better served using a message pump that's using GetMessage rather than PeekMessage, since GetMessage will suspend the thread when the Windows message queue is empty, and you'll only trigger CPU work when something needs to be updated.
Pretty much what the title says.
Im trying to make my own border, like that of visual studio 2015.
Once i have the border working like it should i will add a child window that is the main window for my program, the border will be the parent.
Will also try and add a outer glow once i get it working.
But the problem im having right now is, When i drag my border to resize it to make it smaller, The right or bottom start to get thinner depending on how fast i drag the mouse.
Is there a better way to do this or is there a simple step i can take to fix it.
#include <windows.h>
LPTSTR className_ = TEXT("BorderWindow");
BOOL WINAPI Init(HINSTANCE hInstance, INT cmdShow);
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
INT WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, INT nCmdShow) {
MSG msg;
if (!Init(hInstance, nCmdShow)) {
return FALSE;
}
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (INT)msg.wParam;
}
BOOL WINAPI Init(HINSTANCE hInstance, INT cmdShow)
{
WNDCLASSEX wcex{ 0 };
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = 0;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.hInstance = hInstance;
wcex.hIcon = NULL;
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_HIGHLIGHT + 1);
wcex.lpszClassName = className_;
wcex.hIconSm = NULL;
if (!RegisterClassEx(&wcex)) {
return FALSE;
}
HWND hwnd_ = CreateWindow(className_, className_, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, 200, 500, nullptr, nullptr, hInstance, nullptr);
if (!hwnd_)
return FALSE;
ShowWindow(hwnd_, cmdShow);
UpdateWindow(hwnd_);
return TRUE;
}
void CreateHole(HWND hWnd)
{
HRGN WindowRgn;
HRGN HoleRgn;
//Get the window region:
RECT windowrect;
GetWindowRect(hWnd, &windowrect);
int width = windowrect.right - windowrect.left;
int height = windowrect.bottom - windowrect.top;
WindowRgn = CreateRectRgn(0, 0, width, height);
//Create the hole region:
HoleRgn = CreateRectRgn(2, 2, width - 2, height - 2);
CombineRgn(WindowRgn, WindowRgn, HoleRgn, RGN_DIFF);
SetWindowRgn(hWnd, WindowRgn, TRUE);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_SIZE:
CreateHole(hwnd);
return 0;
case WM_NCCALCSIZE:
// remove default borders
return 0;
case WM_NCHITTEST:
{
RECT rc;
GetClientRect(hwnd, &rc);
POINT pt = { LOWORD(lparam), HIWORD(lparam) };
ScreenToClient(hwnd, &pt);
if (pt.y > (rc.bottom - 5))
{
if (pt.x > (rc.right - 5))
{
return HTBOTTOMRIGHT;
}
}
return HTBORDER;
}
}
return DefWindowProc(hwnd, message, wparam, lparam);
}
If you only need rectangular frame, an easier solution can be achieved as follows:
Window style should be such that normally the whole frame would be shown (WS_CAPTION|WS_POPUP works well for me).
Call DwmExtendFrameIntoClientArea() with MARGINS{0,0,0,1}.
Call SetWindowPos(nullptr, 0, 0, 0, 0, SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_FRAMECHANGED) to recalculate NC area.
Return 0 from WM_NCCALCSIZE if wParam is TRUE. This has the effect of extending the client area to the window size including frame. The regular window frame will be removed, but shadow will still be drawn by DWM (see also remarks section of WM_NCCALCSIZE).
In WM_PAINT draw your frame and content area as you like but make sure to set opaque alpha channel for the margin defined by the DwmExtendFrameIntoClientArea() call. Otherwise part of regular frame would be visible in this area. You may use GDI+ for that as most regular GDI functions ignore alpha channel.
You can put child controls into this window, just as normal. Just make sure child controls don't overlap the margin defined by the DwmExtendFrameIntoClientArea() call because most GDI controls ignore the alpha channel.
I am trying to learn the basics of graphical programming (IN GENERAL, not specifically windows), and would like to use the simplest, most encapsulated methods. I have the following code and would simply like to draw an image to the screen.
Note: The game->update is a call to my own class meant as the main game. I want to handle everything pertaining to my game there. That is why it is in the game loop.
#include <Windows.h>
#include "Asteroid_Game.h"
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg == WM_DESTROY) { PostQuitMessage(0); return 0; }
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPWSTR cmd, int nCmdShow)
{
WNDCLASSEX windowClass;
ZeroMemory(&windowClass, sizeof(WNDCLASSEX));
windowClass.cbSize = sizeof(WNDCLASSEX);
windowClass.hbrBackground = (HBRUSH)COLOR_WINDOW;
windowClass.hInstance = hInstance;
windowClass.lpfnWndProc = WindowProc;
windowClass.lpszClassName = "MainWindow";
windowClass.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&windowClass);
RECT rect = { 0, 0, 1000, 1000 };
AdjustWindowRectEx(&rect, WS_OVERLAPPEDWINDOW, false, WS_EX_OVERLAPPEDWINDOW);
HWND windowHandle = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, "MainWindow", "Asteroids - Pre-Alpha 0.1", WS_OVERLAPPEDWINDOW, 100, 100,
rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, hInstance, 0);
if (!windowHandle)return -1;
ShowWindow(windowHandle, nCmdShow);
MSG message;
message.message = WM_NULL;
Asteroids* game = new Asteroids();
while (message.message != WM_QUIT)
{
if (PeekMessage(&message, NULL, 0, 0, PM_REMOVE))
DispatchMessage(&message);
else
{
// Game Loop:
game->update();
}
delete game;
return 0;
}
I want to draw an image, say with the name "image.png".
I need to know the syntax.
Remember, I want to stay as encapsulated as possible. In other words, the less Windows API, the better.
Thanks for reading.
I have looked at some background drawing tutorials but I still can't draw my background; it's always white. My resources are already in the project. I have tried a few other ways by using paint instead but it still would not draw the background image.
#include <windows.h>
#include <commctrl.h>
#include "resource.h"
HINSTANCE hInst;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
HWND hProgress, hWndBottom;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
hInst = hInstance;
MSG msg = {0};
WNDCLASS wc = {0};
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hbrBackground = CreatePatternBrush( LoadBitmap( hInstance, MAKEINTRESOURCE(IDB_BG) ));//(HBRUSH)(COLOR_BACKGROUND);
wc.lpszClassName = "Test";
if( !RegisterClass(&wc) )
return 1;
if( !CreateWindow(wc.lpszClassName,
"Tests",
WS_POPUPWINDOW|WS_VISIBLE, //WS_OVERLAPPEDWINDOW|WS_VISIBLE
1,1,200,250,0,0,hInstance,NULL))
return 2;
while( GetMessage( &msg, NULL, 0, 0 ) > 0 )
DispatchMessage( &msg );
return 0;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
//Make TopMost
::SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
INITCOMMONCONTROLSEX InitCtrlEx;
InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
InitCtrlEx.dwICC = ICC_PROGRESS_CLASS;
SendMessage(hProgress, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
switch(message)
{
case WM_CREATE:
{
hProgress = CreateWindowEx(0, PROGRESS_CLASS, NULL,
WS_CHILD | WS_VISIBLE | PBS_SMOOTH,
10, 190, 170, 10,
hWnd, NULL, hInst, NULL);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
If you're going to draw a bitmap for your background, you do not just set the background brush to the handle of your bitmap.
Instead, you set the background brush to NULL, and handle the WM_ERASEBKGND message. You respond to it by drawing your bitmap (e.g., with BitBlt or StretchBlt), then you return TRUE (or any other non-zero value) to tell DefWindowProc that the background has been erased, so it shouldn't try to erase it.
Note that if you're doing this in an MDI program, you need to do this in the MDI client window. With MDI, you have a parent window, a client window, and some number of MDI child windows. What looks like the background of the main window is really occupied by the MDI client window, so that's where you need to draw in your background.