|
From: Jason B. <red...@ya...> - 2006-01-01 21:52:37
|
Here is my best attempt at scrolling a bitmap. There
is a bug while trying to resize though. Since a put
this together from missing parts in about half an
hour, that would make sense. Any ideas?
//-------------------------------------------------------------
#include <stdio.h>
#include <string.h>
#include <windows.h>
/* Declare Windows procedure */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM,
LPARAM);
/* Make the class name into a global variable */
char szClassName[ ] = "WindowsApp";
int w,h;
HBITMAP bitmap;
BITMAP bm;
HDC hdc;
HDC hdcmem;
HINSTANCE hinst;
PAINTSTRUCT ps;
SCROLLINFO si;
/* These variables are required by BitBlt.
*/
static HDC hdcWin; /* window DC
*/
static HDC hdcScreen; /* DC for entire screen
*/
static HDC hdcScreenCompat; /* memory DC for screen
*/
static HBITMAP hbmpCompat; /* bitmap handle for old
DC */
static BITMAP bmp; /* bitmap data structure
*/
static BOOL fBlt; /* TRUE if BitBlt
occurred */
static BOOL fScroll; /* TRUE if scrolling
occurred */
static BOOL fSize; /* TRUE if fBlt & WM_SIZE
*/
/* These variables are required for horizontal
scrolling. */
static int xMinScroll; /* minimum horizontal
scroll value */
static int xCurrentScroll; /* current horizontal
scroll value */
static int xMaxScroll; /* maximum horizontal
scroll value */
/* These variables are required for vertical
scrolling. */
static int yMinScroll; /* minimum vertical
scroll value */
static int yCurrentScroll; /* current vertical
scroll value */
static int yMaxScroll; /* maximum vertical
scroll value */
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 */
//replace with any bitmap
bitmap = LoadImage(hinst, "C:\\atomic.bmp",
IMAGE_BITMAP, 0,
0, LR_LOADFROMFILE);
GetObject(bitmap, sizeof(bm), &bm);
w = bm.bmWidth;
h = bm.bmHeight;
/* The Window structure */
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure; /* This
function is called by windows */
wincl.style = CS_BYTEALIGNCLIENT;
/* Catch double-clicks */
wincl.cbSize = sizeof (WNDCLASSEX);
/* Use default icon and mouse-pointer */
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
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_BTNFACE);
/* 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 (
WS_EX_TOPMOST, /*
Extended possibilites for variation */
szClassName, /* Classname */
"Windows App", /* Title Text */
WS_OVERLAPPEDWINDOW | WS_SYSMENU |
WS_VSCROLL | WS_HSCROLL, /* default window */
CW_USEDEFAULT, /* Windows decides the
position */
CW_USEDEFAULT, /* where the window
ends up on the screen */
w/2, /* The programs width
*/
h/2, /* and height in
pixels */
NULL, /* 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)
{
switch (message) /* handle the
messages */
{
case WM_CREATE:
hdc = BeginPaint(hwnd, &ps);
hdcmem = CreateCompatibleDC(hdc);
SelectObject(hdcmem, bitmap);
EndPaint(hwnd, &ps);
/* Initialize the flags. */
fBlt = FALSE;
fScroll = FALSE;
fSize = FALSE;
/* Initialize the horizontal scrolling
variables. */
xMinScroll = 0;
xCurrentScroll = 0;
xMaxScroll = 0;
/* Initialize the vertical scrolling
variables. */
yMinScroll = 0;
yCurrentScroll = 0;
yMaxScroll = 0;
break;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcmem,
xCurrentScroll, yCurrentScroll, SRCCOPY);
EndPaint(hwnd, &ps);
break;
case WM_SIZE: {
int xNewSize;
int yNewSize;
xNewSize = LOWORD(lParam);
yNewSize = HIWORD(lParam);
if (fBlt)
fSize = TRUE;
/*
* The horizontal scrolling range is defined
by
* (bitmap_width) - (client_width). The
current horizontal
* scroll value remains within the horizontal
scrolling range.
*/
xMaxScroll = max(bm.bmWidth-xNewSize, 0);
xCurrentScroll = min(xCurrentScroll,
xMaxScroll);
si.cbSize = sizeof(si);
si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
si.nMin = xMinScroll;
si.nMax = bm.bmWidth;
si.nPage = xNewSize;
si.nPos = xCurrentScroll;
SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);
/*
* The vertical scrolling range is defined by
* (bitmap_height) - (client_height). The
current vertical
* scroll value remains within the vertical
scrolling range.
*/
yMaxScroll = max(bm.bmHeight - yNewSize, 0);
yCurrentScroll = min(yCurrentScroll,
yMaxScroll);
si.cbSize = sizeof(si);
si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
si.nMin = yMinScroll;
si.nMax = bm.bmHeight;
si.nPage = yNewSize;
si.nPos = yCurrentScroll;
SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
UpdateWindow(hwnd);
}
break;
case WM_HSCROLL: {
int xDelta; /* xDelta = new_pos -
current_pos */
int xNewPos; /* new position */
int yDelta = 0;
switch (LOWORD(wParam)) {
/* User clicked the shaft left of the
scroll box. */
case SB_PAGEUP:
xNewPos = xCurrentScroll - 50;
break;
/* User clicked the shaft right of the
scroll box. */
case SB_PAGEDOWN:
xNewPos = xCurrentScroll + 50;
break;
/* User clicked the left arrow. */
case SB_LINEUP:
xNewPos = xCurrentScroll - 5;
break;
/* User clicked the right arrow. */
case SB_LINEDOWN:
xNewPos = xCurrentScroll + 5;
break;
/* User dragged the scroll box. */
case SB_THUMBPOSITION:
xNewPos = HIWORD(wParam);
break;
default:
xNewPos = xCurrentScroll;
}
/* New position must be between 0 and the
screen width. */
xNewPos = max(0, xNewPos);
xNewPos = min(xMaxScroll, xNewPos);
/* If the current position does not change, do
not scroll.*/
if (xNewPos == xCurrentScroll)
break;
/* Set the scroll flag to TRUE. */
fScroll = TRUE;
/* Determine the amount scrolled (in pixels).
*/
xDelta = xNewPos - xCurrentScroll;
/* Reset the current scroll position. */
xCurrentScroll = xNewPos;
/*
* Scroll the window. (The system repaints
most of the
* client area when ScrollWindowEx is called;
however, it is
* necessary to call UpdateWindow in order to
repaint the
* rectangle of pixels that were invalidated.)
*/
ScrollWindowEx(hwnd, -xDelta, -yDelta, (CONST
RECT *) NULL,
(CONST RECT *) NULL, (HRGN) NULL, (LPRECT)
NULL,
SW_INVALIDATE);
UpdateWindow(hwnd);
/* Reset the scroll bar. */
si.cbSize = sizeof(si);
si.fMask = SIF_POS;
si.nPos = xCurrentScroll;
SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);
}
break;
case WM_VSCROLL: {
int xDelta = 0;
int yDelta; /* yDelta = new_pos -
current_pos */
int yNewPos; /* new position */
switch (LOWORD(wParam)) {
/* User clicked the shaft above the scroll
box. */
case SB_PAGEUP:
yNewPos = yCurrentScroll - 50;
break;
/* User clicked the shaft below the scroll
box. */
case SB_PAGEDOWN:
yNewPos = yCurrentScroll + 50;
break;
/* User clicked the top arrow. */
case SB_LINEUP:
yNewPos = yCurrentScroll - 5;
break;
/* User clicked the bottom arrow. */
case SB_LINEDOWN:
yNewPos = yCurrentScroll + 5;
break;
/* User dragged the scroll box. */
case SB_THUMBPOSITION:
yNewPos = HIWORD(wParam);
break;
default:
yNewPos = yCurrentScroll;
}
/* New position must be between 0 and the
screen height. */
yNewPos = max(0, yNewPos);
yNewPos = min(yMaxScroll, yNewPos);
/* If the current position does not change, do
not scroll.*/
if (yNewPos == yCurrentScroll)
break;
/* Set the scroll flag to TRUE. */
fScroll = TRUE;
/* Determine the amount scrolled (in pixels).
*/
yDelta = yNewPos - yCurrentScroll;
/* Reset the current scroll position. */
yCurrentScroll = yNewPos;
/*
* Scroll the window. (The system repaints
most of the
* client area when ScrollWindowEx is called;
however, it is
* necessary to call UpdateWindow in order to
repaint the
* rectangle of pixels that were invalidated.)
*/
ScrollWindowEx(hwnd, -xDelta, -yDelta, (CONST
RECT *) NULL,
(CONST RECT *) NULL, (HRGN) NULL, (LPRECT)
NULL,
SW_INVALIDATE);
UpdateWindow(hwnd);
/* Reset the scroll bar. */
si.cbSize = sizeof(si);
si.fMask = SIF_POS;
si.nPos = yCurrentScroll;
SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
}
break;
case WM_DESTROY:
DeleteDC(hdc);
KillTimer(hwnd, idTimer1);
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;
}
|