Click to See Complete Forum and Search --> : Bitmap on desktop refuses to show


Y0rkieP
July 13th, 2007, 10:32 AM
Hi there,
I'm trying to get a ball that follows the mouse pointer around the screen. To start with I'v made it static to the pointer & it should display below/right of the pointer.

I'v Googled & Yahoo'd, but can only find info on how to do this using a class that someone has made, but I want to learn how to do it myself. So I have written code to achieve this & it compiles fine . No errors are reported in loading the bmp and the point structure seems to be valid from the display of my app window. The only thing I lack is the ball...

Please see code below:

main.cpp (using dev-cpp & win.h definitions fixing GDI problems)

#include <windows.h>
#include "resource.h"

/* Declare Windows procedure */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

/* Make the class name into a global variable */
char szClassName[ ] = "WindowsApp";

int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nFunsterStil)

{
HWND hwnd; /* This is the handle for our window */
MSG messages; /* Here messages to the application are saved */
WNDCLASSEX wincl; /* Data structure for the windowclass */

/* The Window structure */
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */
wincl.style = CS_DBLCLKS; /* Catch double-clicks */
wincl.cbSize = sizeof (WNDCLASSEX);

/* Use default icon and mouse-pointer */
wincl.hIcon = LoadIcon (hThisInstance, MAKEINTRESOURCE(IDI_ICON));
wincl.hIconSm = LoadIcon (hThisInstance, MAKEINTRESOURCE(IDI_ICON));
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL; /* No menu */
wincl.cbClsExtra = 0; /* No extra bytes after the window class */
wincl.cbWndExtra = 0; /* structure or the window instance */
/* Use Windows's default color as the background of the window */
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

/* Register the window class, and if it fails quit the program */
if (!RegisterClassEx (&wincl))
return 0;

/* The class is registered, let's create the program*/
hwnd = CreateWindowEx (
0, /* Extended possibilites for variation */
szClassName, /* Classname */
"Windows App", /* Title Text */
WS_OVERLAPPEDWINDOW, /* default window */
CW_USEDEFAULT, /* Windows decides the position */
CW_USEDEFAULT, /* where the window ends up on the screen */
200, /* The programs width */
100, /* and height in pixels */
HWND_DESKTOP, /* The window is a child-window to desktop */
NULL, /* No menu */
hThisInstance, /* Program Instance handler */
NULL /* No Window Creation data */
);

/* Make the window visible on the screen */
ShowWindow (hwnd, nFunsterStil);

/* Run the message loop. It will run until GetMessage() returns 0 */
while (GetMessage (&messages, NULL, 0, 0))
{
/* Translate virtual-key messages into character messages */
TranslateMessage(&messages);
/* Send message to WindowProcedure */
DispatchMessage(&messages);
}

/* The program return-value is 0 - The value that PostQuitMessage() gave */
return messages.wParam;
}


/* This function is called by the Windows function DispatchMessage() */

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HINSTANCE hInstance;
POINT ptCursor;

HWND hDesk;
HDC hDeskDC;
HBITMAP bmBall;
BITMAP bm;

char szInfo[40]; int iLen;
switch (message) /* handle the messages */
{
case WM_CREATE:
{
HINSTANCE hInstance = ((LPCREATESTRUCT) lParam)->hInstance;
hDesk = GetDesktopWindow();
//hDeskDC = GetDC(hDesk);
bmBall = LoadBitmap (hInstance, MAKEINTRESOURCE(IDB_IMAGE));
if (bmBall == NULL)
{
MessageBox (hwnd, "resource not loaded..", "Error", MB_OK);
}
int obj = GetObject (bmBall, sizeof (BITMAP), &bm);
if (obj == NULL)
{
MessageBox (hwnd, "error with GetObject()..", "Error", MB_OK);
}
SetTimer(hwnd, 1, 100, NULL);
}
break;

case WM_TIMER:
{
InvalidateRect(hwnd, NULL, FALSE);
}
break;

case WM_PAINT:
{
HDC hDC, hdcMem;
PAINTSTRUCT ps;

GetCursorPos (&ptCursor);

hDC = BeginPaint (hwnd, &ps);
hDeskDC = GetDC(hDesk);
//hdcMem = CreateCompatibleDC(hDC);
hdcMem = CreateCompatibleDC(hDeskDC); // Will ball show?

SelectObject (hdcMem, bmBall);
TransparentBlt(hDeskDC, (ptCursor.x + 32), (ptCursor.y + 32), 28, 28, hdcMem, 0, 0, 28, 28, RGB(255, 0, 255));

DeleteDC (hdcMem);
DeleteDC(hDeskDC);

iLen = wsprintf (szInfo, "x = %d ", ptCursor.x);
TextOut (hDC, 0, 0, szInfo, iLen);
iLen = wsprintf (szInfo, "y = %d ", ptCursor.y);
TextOut (hDC, 0, 32, szInfo, iLen);

EndPaint (hwnd, &ps);
//InvalidateRect(hDesk, NULL, FALSE); // Still wont show ball
}
break;

case WM_DESTROY:
{
KillTimer (hwnd, 1);
//DeleteDC(hDeskDC);
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;
}


resource.h

#define IDI_ICON 1000
#define IDB_IMAGE 1010


resource.rc

#include "resource.h"

IDB_IMAGE BITMAP "c:\\dev-cpp\\examples\\Bmp2Scr\\Ball.bmp"

IDI_ICON ICON "c:\\dev-cpp\\examples\\Bmp2Scr\\Icon.ico"


As you can see, I'v tryed different things, but with no apparrent success. It's possibly something small that i'v missed. As usual, my thanks in advance for any help given...

olivthill
July 13th, 2007, 02:18 PM
Your variables, bmBall and bm, should be static, or global. Otherwise, they are initialized once, when the WM_CREATE message is processed. Then, when a new message is processed, e.g. WM_PAINT, bmBall and bm contain what is on the stack at that time, which may not be the value they had when they were initialized.
(This is the first thing that I have seen, but there may be other problems.)

Y0rkieP
July 14th, 2007, 09:08 AM
Hi olivthill,
yep, thats it - I needed to make bmBall static. The ball now shows correctly - maybe I should have spotted that point. Thanks for your help.

I still have one issue that the desktop won't refresh. I'v tryed un-commenting InvalidateRect and using SendMessage (hDesk, WM_Paint, NULL, NULL). As yet - no joy there. but thats something to work on.

InvalidateRect(NULL, NULL, FALSE) does force a refresh, but creates a lot of screen flicker and looks quite ugly. One idea i do have is to make a bitmap of the part of the desktop where the ball is drawen, then it can be replaced when the ball is to be moved.

Cheers to you, olivthill, for spotting that...

VladimirF
July 14th, 2007, 01:34 PM
...I still have one issue that the desktop won't refresh...That is because you can't (well, shouldn't) paint in other people's windows!
The rule-of-thumb is: only paint in response to WM_PAINT message. And you don't... No, you don't! Although the code is in your WM_PAINT handler, it doesn't paint YOUR hDC. And you are NOT in desktop's WM_PAINT handler.
What is the task you are trying to implement? Have a "ball" following the cursor? You could create a topmost window in a shape of your ball and move it around on a timer to where the cursor is.

Y0rkieP
July 15th, 2007, 11:23 AM
Hi Vladimir,
Yes, basically I'm trying to learn more about programming using bitmaps. I'v done several apps that use bitmaps in various ways & I just thought it may be fun to create an animated ball that follows the mouse pointer, though such a thing wouldnt have much functionality. I'v forgone the animated bit for now to concentrate on the basics.

It never crosed my mind to use a window, I have allways placed windows static to the desktop (though I have used screen resolution with this). Using a window for this & moving the window around does sound more sensible.

Maybe my problem is that I tend to take the wrong approach to the task at hand. Maybe I need to take a little more time planning, rarther than just plan & jump in coding.

Thanks for your your advice Vladimir...

VladimirF
July 15th, 2007, 06:54 PM
...basically I'm trying to learn more about programming using bitmaps. I'v done several apps that use bitmaps in various ways & I just thought it may be fun to create an animated ball that follows the mouse pointer...You can do this in your own window. You won't even need timer - only WM_MOUSEMOVE messages.