Drawing on window at background level on Windows only works once and requires a relog to work again - c++

I'm having an issue where if I get ProgMan to create a WorkerW window behind the desktop icons (as described by https://stackoverflow.com/a/56132585/5923516), it allows me to draw to it the first time, but if I stop it and then try and run it again, it fails to draw. By 'fails to draw', I mean that I don't see any errors, but it just doesn't do anything. I've also tried to debug it and none of the effected values change (i.e. the wallpaper_hwnd variable points to the same place, and none of the SDL functions return error values) I've verified this behaviour on both Windows 10 and 11, both using different video drivers. The only way I've found to fix this is to log out then log back in, which doesn't really help.
Once exited I also noticed that the background instantly changes back to the wallpaper picture/colour. But I don't know if that information is useful.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <shellapi.h>
// Can also be <SDL.h> depending on the install of SDL
#include <SDL2/SDL.h>
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) {
HWND ShellHandle = FindWindowEx(hwnd, NULL, "SHELLDLL_DefView", NULL);
HWND *ret = (HWND *) lParam;
if (ShellHandle) {
*ret = FindWindowEx(NULL, hwnd, "WorkerW", NULL);
}
return true;
}
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int ShowCmd) {
// Get the ProgMan Window
HWND progman = FindWindow("ProgMan", NULL);
// Get ProgMan to create a WorkerW
SendMessageTimeout(progman, 0x052C, 0, 0, SMTO_NORMAL, 1000, nullptr);
// Find the WorkerW that was spawned
HWND wallpaper_hwnd = nullptr;
EnumWindows(EnumWindowsProc, (LPARAM) &wallpaper_hwnd);
// Init SDL2
SDL_Init(SDL_INIT_VIDEO);
// Create an SDL Window from this
SDL_Window* sdl_window = SDL_CreateWindowFrom((void*)wallpaper_hwnd);
// Create SDL Renderer from the SDL Window
SDL_Renderer* renderer = SDL_CreateRenderer(sdl_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
// Clear the window as a test
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
// Sleep for 1 second so that the change is actually visible
Sleep(1000);
// Clean up
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(sdl_window);
SDL_Quit();
// In my testing this doesn't fix it:
// DestroyWindow(wallpaper_hwnd);
return 0;
}
If anyone can work out why I'm getting these issues then I would greatly appreciate it.
EDIT:
After messing around a bit, I've found that wintabbing makes it work again. This still isn't a very good solution, however.

Related

C++ changing image on user input in WinAPI

I am having issues in getting my .bmp image displayed to change to another one on user input. The image can be successfully printed at the start (title.bmp), but is supposed to change when pressing 1 or 2 followed by enter (to introduction.bmp & start.bmp). I must be missing something!
Where this happens is around the bottom of the code from while (running == 1) { so skip down to there.
I am using loadImage("title.bmp"); to print my images (I change the filename appropriately of course), and cin >> menuSelection; to pause the program and wait until the user presses one or two followed by enter.
I've searched many, many pages on how to print and change images in WinAPI, and this is the closest I can get. If there is any other information I have missed please tell me and I will comment it. Thanks in advance for helping!
//These are the libraries (external files) to include at the start.
#include <cstdio>
#include <windows.h>
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <string>
using namespace std;
//Defining the [global] variables that will be used throughout the program
int running = 1;
int menuSelection = 0;
int userInput;
int userInputDummy;
int intPointer;
//Starter variables used in creating a window and printing images. These are global.
HDC imageDC; // the DC to hold our image
HBITMAP imageBmp; // the actual bitmap which contains the image (will be put in the DC)
HBITMAP imageBmpOld; // the DC's old bitmap (for cleanup)
const int screenSize_X = 640;
const int screenSize_Y = 480;
//Functions! Sections of code to re-used in the program
// Function to load the image into our DC so we can draw it to the screen
void loadImage(const char* pathname)
{
imageDC = CreateCompatibleDC(NULL); // create an offscreen DC
imageBmp = (HBITMAP)LoadImageA( // load the bitmap from a file
NULL, // not loading from a module, so this is NULL
pathname, // the path we're loading from
IMAGE_BITMAP, // we are loading a bitmap
0, 0, // don't need to specify width/height
LR_DEFAULTSIZE | LR_LOADFROMFILE// use the default bitmap size (whatever the file is), and load it from a file
);
imageBmpOld = (HBITMAP)SelectObject(imageDC, imageBmp); // put the loaded image into our DC
}
// Function to clean up
void cleanUpImage()
{
SelectObject(imageDC, imageBmpOld); // put the old bmp back in our DC
DeleteObject(imageBmp); // delete the bmp we loaded
DeleteDC(imageDC); // delete the DC we created
}
// The function to draw our image to the display (the given DC is the screen DC)
void drawImage(HDC screen)
{
BitBlt(
screen, // tell it we want to draw to the screen
0, 0, // as position 0,0 (upper-left corner)
screenSize_X, // width of the rect to draw
screenSize_Y, // height of the rect
imageDC, // the DC to get the rect from (our image DC)
0, 0, // take it from position 0,0 in the image DC
SRCCOPY // tell it to do a pixel-by-pixel copy
);
}
// A callback to handle Windows messages as they happen
LRESULT CALLBACK wndProc(HWND wnd, UINT msg, WPARAM w, LPARAM l)
{
// what kind of message is this?
switch (msg)
{
// we are interested in WM_PAINT, as that is how we draw
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC screen = BeginPaint(wnd, &ps); // Get the screen DC
drawImage(screen); // draw our image to our screen DC
EndPaint(wnd, &ps); // clean up
}break;
// we are also interested in the WM_DESTROY message, as that lets us know when to close the window
case WM_DESTROY:
PostQuitMessage(0);
break;
}
// for everything else, let the default window message handler do its thing
return DefWindowProc(wnd, msg, w, l);
}
// A function to create the window and get it set up
HWND createWindow(HINSTANCE inst)
{
WNDCLASSEX wc = { 0 }; // create a WNDCLASSEX struct and zero it
wc.cbSize = sizeof(WNDCLASSEX); // tell windows the size of this struct
wc.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW)); // tell it to use the normal arrow cursor for this window
wc.hInstance = inst; // give it our program instance
wc.lpfnWndProc = wndProc; // tell it to use our wndProc function to handle messages
wc.lpszClassName = TEXT("DisplayImage"); // give this window class a name.
RegisterClassEx(&wc); // register our window class with Windows
// the style of the window we want... we want a normal window but do not want it resizable.
int style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU; // normal overlapped window with a caption and a system menu (the X to close)
// Figure out how big we need to make the window so that the CLIENT area (the part we will be drawing to) is
// the desired size
RECT rc = { 0,0,screenSize_X,screenSize_Y }; // desired rect
AdjustWindowRect(&rc, style, FALSE); // adjust the rect with the given style, FALSE because there is no menu
return CreateWindow( // create the window
TEXT("DisplayImage"), // the name of the window class to use for this window (the one we just registered)
TEXT("Display an Image"), // the text to appear on the title of the window
style | WS_VISIBLE, // the style of this window (OR it with WS_VISIBLE so it actually becomes visible immediately)
100, 100, // create it at position 100,100
rc.right - rc.left, // width of the window we want
rc.bottom - rc.top, // height of the window
NULL, NULL, // no parent window, no menu
inst, // our program instance
NULL); // no extra parameter
}
//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// _________________________________________________________________________________________
// The actual entry point for the program!
// This is Windows' version of the 'main' function:
int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmd, int show)
{
// load our image
loadImage("title.bmp");
// create our window
HWND wnd = createWindow(inst);
// Do the message pump! keep polling for messages (and respond to them)
// until the user closes the window.
MSG msg;
while (GetMessage(&msg, wnd, 0, 0)) // while we are getting non-WM_QUIT messages...
TranslateMessage(&msg); // translate them
DispatchMessage(&msg); // and dispatch them (our wndProc will process them)
{
while (running == 1) {
//Welcoming the user to the program, and asking them what they want to do (starts functions)
cin >> menuSelection;
//Selecting the introduction option
if (menuSelection == 1) {
loadImage("introduction.bmp");
cin >> userInputDummy;
menuSelection = 0;
}
//Selecting the start option
else if (menuSelection == 2) {
loadImage("start");
cin >> userInputDummy;
menuSelection = 0;
}
//Selecting the exit option
else if (menuSelection == 3) {
menuSelection = 0;
running = 0;
}
}
// once the user quits....
cleanUpImage();
return 0;
return EXIT_SUCCESS;
}
}
you cannot use cin in win32 use an editbox then get the user's input from it as character string then if you want convert it to an integer value otherwise use the API:
GetDlgItemInt(...);
you are also handling only GetMessage in while-loop while you only handle dispatchmessage outside the loop which means you handle it only once, when getmessage fails (the end of program) so the result is a freezing windows as long as there's no one who takes messages from getmessage to the target windo.
the solution: make DispatchMessage inside while loop:
another thing: you pass hwnd to getmessage the result destroying the window won't make the application exit.
take a look at GetMessage() when passing a non-null value:
link text
the correct thing in your case:
while (GetMessage(&msg, 0, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
* don't load image inside loop just load at the time wanted:
make an edit box with style ES_NUMBER and another button names for example change image so when clicked take the content of edit box convert it to integer, check whether it is 1 or 2 then load imaged depending the value.
you may ask "why I can't use iostream input and output streams in win32" because I ask you "where is console windows?" and if it is here what is the role of while-loop (blocking waiting for messages)?

Properly Link Libraries in the Command Line

Preface: I'm fairly new to C++ and am just beginning to seriously program.
Post-Preface: I tried to post a link for the functions/pages I mention in this post, but Stack Overflow yelled at me because I don't have enough reputation to post more than two links.
I'm attempting to make a few simple GUIs in C++ with the Windows API using MinGW and the command line. I'm trying to change the window background, and one function which helps do this is the CreateSolidBrush function. This function requires the gdi32 library, but each time I try to compile/link to this library, I receive an error along the lines of "can't find that library, sucka".
Page1 and page2 provide useful information about MinGW's library functionality. Stack Overflow post # 5683058 and # 17031290 describe what I think are similar questions/problems to mine. I've searched far and wide for a simple and direct answer about how to link files/libraries from other directories (especially Windows libraries), but no luck in implementing the knowledge from these pages. Perhaps the answer is staring me right in the face, but my valiant efforts to "see the cat, draw the tiger" are in vain. It's possible that I'm entering the incorrect path/name (lib vs dll?), or maybe I'm completely overlooking something more fundamental (missing a header?). One command I've tried to use is
g++ -LC:\WINDOWS\System32 -lgdi32 gui.cpp
but this doesn't seem to work (note: source file named "gui.cpp").
Question 1: To start simple, what is the proper notation/command to link to individual header/source files which are not in the current directory?
Question 2: What is the proper notation/command to link to a library which is in the current directory?
Question 3: What is the proper notation/command to link to a library which is not in the current directory?
I realize these questions are sorta-kinda answered in a variety of ways on other pages, but they're often mingled with directions regarding Visual Studio, Eclipse, Code::Blocks, etc. and therefore unclear for the novices who forgo the luxuries of an IDE. I would appreciate a straightforward answer for your typical, run-of-the-mill noob. Many thanks in advance for any help or guidance.
I'll post my code, but I'm thinking only a couple of the first five lines are relevant:
#include <windows.h>
#include <string>
COLORREF desired_color = RGB(200,200,200);
HBRUSH hBrush = CreateSolidBrush(desired_color);
static char str_class_name[] = "MyClass";
static char str_titlebar[] = "My Window Title";
static int window_width = 300;
static int window_height = 300;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
static HINSTANCE program_global_instance = NULL;
int WINAPI WinMain(HINSTANCE program_current_instance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
program_global_instance = program_current_instance;
WNDCLASSEX window_class;
HWND window_handle;
MSG window_message;
window_class.cbSize = sizeof(WNDCLASSEX); // size of struct; always set to size of WndClassEx
window_class.style = 0; // window style
window_class.lpfnWndProc = WndProc; // window callback procedure
window_class.cbClsExtra = 0; // extra memory to reserve for this class
window_class.cbWndExtra = 0; // extra memory to reserve per window
window_class.hInstance = program_global_instance; // handle for window instance
window_class.hIcon = LoadIcon(NULL, IDI_APPLICATION); // icon displayed when user presses ALT+TAB
window_class.hCursor = LoadCursor(NULL, IDC_ARROW); // cursor used in the program
window_class.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); // brush used to set background color
window_class.lpszMenuName = NULL; // menu resource name
window_class.lpszClassName = str_class_name; // name with which to identify class
window_class.hIconSm = LoadIcon(NULL, IDI_APPLICATION); // program icon shown in taskbar and top-left corner
if(!RegisterClassEx(&window_class)) {
MessageBox(0, "Error Registering Class!", "Error!", MB_ICONSTOP | MB_OK);
return 0;
}
window_handle = CreateWindowEx(
WS_EX_STATICEDGE, // dwExStyle: window style
str_class_name, // lpClassName: pointer to class name
str_titlebar, // lpWindowName: window titlebar
WS_OVERLAPPEDWINDOW, // dwStyle: window style
CW_USEDEFAULT, // x: horizontal starting position
CW_USEDEFAULT, // y: vertical starting position
window_width, // nWidth: window width
window_height, // nHeight: window height
NULL, // hWndParent: parent window handle (NULL for no parent)
NULL, // hMenu: menu handle (Null if not a child)
program_global_instance, // hInstance : current window instance
NULL // lpParam -Points to a value passed to the window through the CREATESTRUCT structure.
);
if (window_handle == NULL) {
MessageBox(0, "Error Creating Window!", "Error!", MB_ICONSTOP | MB_OK);
return 0;
}
ShowWindow(window_handle, nCmdShow);
UpdateWindow(window_handle);
while(GetMessage(&window_message, NULL, 0, 0)) {
TranslateMessage(&window_message);
DispatchMessage(&window_message);
}
return window_message.wParam;
}
// window_handle: window ID
// uMsg: window message
// wParam: additional message info; depends on uMsg value
// lParam: additional message info; depends on uMsg value
LRESULT CALLBACK WndProc(
HWND window_handle,
UINT Message,
WPARAM wParam,
LPARAM lParam
) {
switch(Message) {
case WM_CLOSE:
DestroyWindow(window_handle);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(window_handle, Message, wParam, lParam);
}
return 0;
}
Question 1: To start simple, what is the proper notation/command to link to individual header/source files which are not in the current directory?
That's not linking, that's compiling/including (unless you compile those source files to object files, first).
So:
gcc {other options} -o gui.exe gui.cpp /path/to/source_file_one.cpp /path/to/source_file_n.cpp
or, compile the others first:
gcc {other options} -c -o source_file_one.o /path/to/source_file_one.cpp
gcc {other options} -c -o source_file_n.o /path/to/source_file_n.cpp
gcc {other options} -o gui.exe source_file_n.o source_file_one.o gui.cpp
-c tells gcc not to try and link things together, as this is done in the last step.
{other options} can contain -I{include dirs} to inform gcc where to look when you #include something.
Question 2: What is the proper notation/command to link to a library which is in the current directory?
See 3; -L. should work.
Question 3: What is the proper notation/command to link to a library which is not in the current directory?
You're doing it right, so far: -L tells gcc about paths to look into for libraries, and -l{libname} links against a library.

Maximize/Minimize window from another thread

I'm trying to find out the correct way to minimize/maximize a window owned by another thread. My target window can be fullscreen or not (i should be able to minimize and maximize it regardless of its state). I've tried various combinations of ShowWindow SW_MINIMIZE, SW_MAXIMIZE, SW_FORCEMINIMIZE etc... but the only result i've been able to achieve was restoring it (maximizing) when it was minimized AND fullscreen with ShowWindow(hWnd, SW_RESTORE).
Here it is the code i'm using to retrieve my handle:
#include <Windows.h>
#include <iostream>
// I'm a console application
int main(int argc, char* argv[]) {
HWND hWnd = FindWindow(TEXT("MyWindowClass"), NULL);
if(IsWindow(hWnd)) {
std::cout << "Window found!" << std::endl;
SetForegroundWindow(hWnd); // I'll give focus to my window. This is always working.
if(IsIconic(hWnd))
ShowWindow(hWnd, SW_RESTORE); // This is working only if the window is minimized while in fullscreen mode
Sleep(3000);
ShowWindow(hWnd, SW_MINIMIZE); // Not working. SW_FORCEMINIMIZE, SW_HIDE etc are not working either.
}
return 0;
}
After struggling for a whole day I've found a solution that works for both minimizing and maximizing the window regardless of its state: Post/SendMessage.
To maximize it:
PostMessage(hWnd, WM_SYSCOMMAND, SC_RESTORE, 0);
To minimize it:
PostMessage(hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
Try ShowWindow first, and then call SetForegroundWindow:
void show_and_setforeground(HWND hwnd)
{
WINDOWPLACEMENT place;
memset(&place, 0, sizeof(WINDOWPLACEMENT));
place.length = sizeof(WINDOWPLACEMENT);
GetWindowPlacement(hwnd, &place);
switch (place.showCmd)
{
case SW_SHOWMAXIMIZED:
ShowWindow(hwnd, SW_SHOWMAXIMIZED);
break;
case SW_SHOWMINIMIZED:
ShowWindow(hwnd, SW_RESTORE);
break;
default:
ShowWindow(hwnd, SW_NORMAL);
break;
}
SetForegroundWindow(hwnd);
}
In addition to IsWindow(hWnd) you may want to use IsWindowVisible(hWnd) because some programs use invisible windows which are not meant to be used.
hwnd = FindWindow(TEXT("MyWindowClass"), NULL);
if (IsWindow(hwnd))
{
if(IsWindowVisible(hwnd))//optional
{
show_and_setforeground(hwnd);
...
}
}

Successful build with createWindowEx, window still won't appear

I'm trying to learn some windows and directX programming and I was messing around trying some different things. When suddently my the windows stopped appearing, even tho it was a successful build. I figured I must have messed something up and I undid everything until i got back to the place where I last managed to get the window to appear, but now when I run (with a successful build) it still doesn't show :( And I'm starting to run out of ideas what the problem could be, it so strange. One of the thing I did since last time I got it to work was add some libs directories but I have a hard time seeing how that would affect the program this way. Have anyone of you run in to this problem before, and if so how did you solve it? Here is the code of the func creating the window (and yes I am aware of the infinite loop, it shouldn't cause this problem tho, right?) :
ps. I have also tried changing between WINDCLASSEX and WINDCLASS, with all the functions that need to be change with it, didn't make any difference ds.
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;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
RegisterClass(&wc);
RECT wr = {0, 0, 500, 400}; // set the size, but not the position
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE); // adjust the size
// Create the window.
HWND hwnd = CreateWindowEx(
0, // Optional window styles.
CLASS_NAME, // Window class
L"My first window", // Window text
WS_OVERLAPPEDWINDOW, // Window style
CW_USEDEFAULT, CW_USEDEFAULT,//position x,y
wr.right-wr.left, wr.bottom-wr.top,//width, height
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
if (hwnd == NULL){
return 0;
}
InitD3D(hwnd);
// Run the message loop.
MSG msg = { };
while (true){
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else{
}
}
return 0;
}
looks like you need a ShowWindow call in there (unless InitD3D does that, you haven't shown the code)
windows are by default created non-visible, so that you can do various initialization without the user seeing what goes on
as an alternative you can create the window already visible, but generally it's a good idea to keep to a single convention
by the way, you can just use a standard int main, no need to use the Microsoft monstrosity
with GNU toolchain that's all, with Microsoft's tools you then have to tell the linker to accept the standard code, if you use the GUI subsystem, via linker option /entry:mainCRTStartup.
also, the call to non-blocking PeekMessage means your message loop will most likely be a CPU hog
instead, use blocking GetMessage
and remember to exit the loop when GetMessage returns 0 (which indicates a WM_QUIT message has been posted)

Image wont draw to screen C++

I am following a tutorial. And I am trying to draw a .bmp file to the screen. It builds with no errors but no image appears. according to the book, I should see the image pop up in random places. Below is my code. The author doesnt recommend this technique for drawing objects, he is just doing for demostration. In case your wondering.
The image is a 25x25 square red square.
#include <windows.h>
#include <iostream>
#include <time.h>
using namespace std;
const string APPTITLE = "Game Loop";
HWND window;
HDC device;
bool gameover = false;
void DrawBitmap(char *filename, int x, int y)
{
//load the bitmap image
HBITMAP image = (HBITMAP)LoadImage(0,"c.bmp", IMAGE_BITMAP,0,0, LR_LOADFROMFILE);
BITMAP bm;
GetObject(image, sizeof(BITMAP), &bm);
HDC hdcImage = CreateCompatibleDC(device);
SelectObject(hdcImage,image);
BitBlt(
device,
x,y,
bm.bmWidth, bm.bmHeight,
hdcImage,
0,0,
SRCCOPY);
//deletec the device context and bitmap
DeleteDC(hdcImage);
DeleteObject((HBITMAP)image);
}
bool Game_Init()
{
srand(time(NULL));
return 1;
}
void Game_Run()
{
if(gameover == true) return;
RECT rect;
GetClientRect(window, &rect);
//draw bitmap at random location
int x = rand() % (rect.right - rect.left);
int y = rand() % (rect.bottom - rect.top);
DrawBitmap("c.bmp",x,y);
}
void Game_End()
{
//free the device
ReleaseDC(window,device);
}
LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM WParam, LPARAM lparam)
{
switch(message)
{
case WM_DESTROY:
gameover = true;
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, message, WParam, lparam);
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
//set the new windows properties
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC) WinProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName= APPTITLE.c_str();
wc.hIconSm = NULL;
return RegisterClassEx(&wc);
}
bool InitInstance(HINSTANCE hInstance, int nCmdShow)
{
//create a new window
window = CreateWindow(
APPTITLE.c_str(),
APPTITLE.c_str(),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
640,480,
NULL,
NULL,
hInstance,
NULL);
//was there an error creating the window ?
if(window == 0) return 0;
//display the window
ShowWindow(window, nCmdShow);
UpdateWindow(window);
device = GetDC(window);
return 1;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
//declare variables
MSG msg;
//register the class
MyRegisterClass(hInstance);
//initialize application
if(!InitInstance(hInstance, nCmdShow)) return 0;
//initilize the game
if(!Game_Init()) return 0;
//main message loop
while(!gameover)
{
if(PeekMessage(&msg,NULL, 0, 0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Game_Run();
}
Game_End();
return msg.wParam;
}
I am not sure if its because I have the image in the wrong location. but if that was the case. I figure it would throw a error. I have the image placed at the root of my source folder.
[EDIT]
Also , when I rebuild, I get a warning which might be a cause but here is the warning
1>------ Rebuild All started: Project: Begin, Configuration: Debug Win32 ------
1>Deleting intermediate and output files for project 'Begin', configuration 'Debug|Win32'
1>Compiling...
1>main.cpp
1>c:\users\numerical25\documents\visual studio 2008\projects\begin\begin\main.cpp(39) : warning C4244: 'argument' : conversion from 'time_t' to 'unsigned int', possible loss of data
1>Compiling manifest to resources...
1>Microsoft (R) Windows (R) Resource Compiler Version 6.1.6723.1
1>Copyright (C) Microsoft Corporation. All rights reserved.
1>Linking...
1>LINK : C:\Users\numerical25\Documents\Visual Studio 2008\Projects\Begin\Debug\Begin.exe not found or not built by the last incremental link; performing full link
1>Embedding manifest...
1>Microsoft (R) Windows (R) Resource Compiler Version 6.1.6723.1
1>Copyright (C) Microsoft Corporation. All rights reserved.
1>Build log was saved at "file://c:\Users\numerical25\Documents\Visual Studio 2008\Projects\Begin\Begin\Debug\BuildLog.htm"
1>Begin - 0 error(s), 1 warning(s)
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========
The code does work, you just forgot to put your c.bmp in the right location. Put it in the project output folder (i.e. bin/Debug) if you're launching the program from Explorer or to the project folder if you're lanching the program from Visual Studio.
Your code seems to work, for a sufficiently loose definition of "work". Unless you've modified the code (quite a bit) in attempting to make it work, my advice would be to find a different tutorial to follow -- at least to me, most of what's there right now is quite unimpressive.
Just for example, Game_Run() passes the name of the bitmap file as a parameter to Draw_Bitmap(), but the parameter gets ignored, and Draw_Bitmap() uses a hard-coded file name instead.
The PeekMessage() loop makes the program look like it was written about 25 years ago, in the days of 16-bit Windows (and arguably not so great even then). There's rarely (if ever) a good reason to use PeekMessage() in a new code, and code that did use it is probably overdue for an overhaul. The main loop normally uses GetMessage(), and you can (for example) use SetTimer (with a duration of 0) to compute new coordinates for drawing the bitmap, and then calling InvalidateRect() to get it drawn. At one time there was a fair argument that the extra messages involved in this caused excessive overhead, but on a modern machine it'll keep up with the monitor refresh rate while using on the order of 10% of the CPU or less.
To keep CPU usage down, however, you want to restructure the code a bit -- right now, every time you draw, you're getting the window rectangle, reloading the BMP from disk, selecting the BMP into a compatible DC, and finally BitBlting to get the image to the screen. That's the part of the code where optimization will make a difference -- by strong preference, you want it to just call BitBlt and be done. The rest of the code should be moved elsewhere so it happens only when needed. For example, you can retrieve the window rectangle in response to WM_SIZE, and just save it in-between. Since you're using the same bitmap for the duration, load it once, and from them on just display it.