home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C!T ROM 5
/
ctrom5b.zip
/
ctrom5b
/
PROGRAM
/
DIVERSEN
/
IMGLIB12
/
TSTAPP.C
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-25
|
74KB
|
2,466 lines
/****************************************************************************
Copyright (c) 1994, 1995 by SimSoft
PROGRAM: testapp.c
PURPOSE: Test program to exercise the functionality of ImgLib
Revision History:
Nov 6, 94 Beta release
Dec 18, 94 Release 1.0
Feb 19, 95 Release 1.1: Added support for file saving, scrolling, sizing
printing
Mar 25, 95 Release 1.2: Removed references to unsupported image types.
Added clipdoard operations by utilizing ClipDIB
Added the "Zoom x5" feature.
Simplified palette handling.
****************************************************************************/
#include <windows.h>
#include <commdlg.h>
#ifndef WIN32
#include <print.h>
#endif
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include "tstapp.h"
#include "imglib.h"
#ifdef USE_WING
#include <wing.h>
typedef HDC (WINGAPI *WINGCREATEDC) (void);
typedef HBITMAP (WINGAPI *WINGCREATEBITMAP) (HDC, BITMAPINFO const FAR *, void FAR *FAR *);
typedef BOOL (WINGAPI *WINGSTRETCHBLT) (HDC, int, int, int, int, HDC, int, int, int, int);
WINGSTRETCHBLT fpWinGStretchBlt;
WINGCREATEBITMAP fpWinGCreateBitmap;
WINGCREATEDC fpWinGCreateDC;
#endif
#ifdef WIN32
#define huge
#define CONTROL_ID(w) (LOWORD (w))
#define allocmem(s) (malloc (s))
#define freemem(p) (free (p))
#define copymem(d, s, c) (memcpy (d, s, c))
#else
#define CONTROL_ID(w) (w)
#define allocmem(s) (GlobalLock (GlobalAlloc (GHND, (DWORD)s)))
#define freemem(p) (GlobalFree (LOWORD (GlobalHandle (HIWORD (p)))))
#define copymem(d, s, c) (hmemcpy (d, s, c))
#endif
typedef char huge * HPSTR;
#define WINDOW_NAME "ImgLib Test App"
#define MENU_POSITION_ROTATE 5
#define MENU_POSITION_MIRROR 6
#define MENU_POSITION_TC_OPT 0
static HWND hwndMain;
static HINSTANCE hInst;
static char szBuffer[256];
static HINSTANCE hWinGInst;
static HACCEL hAccel;
static LPVOID lpDIB1, lpDIB2, lpDIBDisplay;
static HPALETTE hPalette;
static LPPRINTDLG pPrintDlgStruct;
static BOOL bHalftoneImgLib, bFillPage;
static unsigned int uPrintCopies = 1;
static RECT rcSelection;
static POINT ptAnchor;
static BOOL bDrawSelection, bPasting;
static HDC hdcWinG;
static HBITMAP hbmpWinG, hbmpWinGOld;
static BOOL InitApplication (HANDLE);
static BOOL InitInstance (HANDLE, int);
LRESULT CALLBACK MainWndProc (HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK AboutProc (HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK FileTypeProc (HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK BrightnessProc (HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK PrintProc (HWND, UINT, WPARAM, LPARAM);
static BOOL GetOpenFile (LPSTR);
static BOOL GetSaveFile (LPSTR);
LPVOID CreateDisplayDIB (HWND, LPVOID*, HPALETTE *);
static void UpdateWindowTitle (LPSTR, BOOL);
static void ResizeWindowToDIB (HWND, LPVOID);
static void HandleVerticalScroll (WPARAM, LPARAM);
static void HandleHorizontalScroll (WPARAM, LPARAM);
static void HandleWindowSizing (LPVOID, WPARAM, LPARAM);
static void HandlePrinting (LPVOID);
static void HandleMenuPopup (WPARAM, LPARAM);
static void InitializePrintStruct (void);
static void HandleLButtonDown (WPARAM, LPARAM);
static void HandleLButtonUp (WPARAM, LPARAM);
static void HandleMouseMove (WPARAM, LPARAM);
static void HandleRButtonDown (WPARAM, LPARAM);
static void HandleCharacter (WPARAM, LPARAM);
static void HandlePasting (WPARAM, LPARAM);
static void HandleCopying (WPARAM, LPARAM);
static void HandleZoomin (WPARAM, LPARAM);
static void DrawSelectionBox (void);
static void EraseSelectionBox (void);
static void ProcessNewDIB (LPVOID);
static LRESULT HandlePaintingAndUpdates (UINT, WPARAM, LPARAM);
#ifdef USE_WING
static void InitializeWinG (void);
static void UpdateWinGBitmap (LPVOID);
#endif
/****************************************************************************
FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
PURPOSE: calls initialization function, processes message loop
****************************************************************************/
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
hInst = hInstance;
if (!hPrevInstance)
{
if (!InitApplication (hInstance))
return (FALSE);
}
if (!InitInstance (hInstance, nCmdShow))
return (FALSE);
while (GetMessage (&msg, NULL, 0, 0xffff))
{
if (!TranslateAccelerator (hwndMain, hAccel, &msg))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
}
return (0);
}
/****************************************************************************
FUNCTION: InitApplication(HANDLE)
PURPOSE: Initializes window data and registers window class
****************************************************************************/
BOOL InitApplication (HANDLE hInstance)
{
WNDCLASS wc;
wc.style = 0;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor (NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject (WHITE_BRUSH);
wc.lpszMenuName = "tstappmenu";
wc.lpszClassName = "Test App";
return (RegisterClass (&wc));
}
/****************************************************************************
FUNCTION: InitInstance(HANDLE, int)
PURPOSE: Saves instance handle and creates main window
****************************************************************************/
BOOL InitInstance (HANDLE hInstance, int nCmdShow)
{
UINT uErrMode;
HMENU hMenu;
HDC hDC;
hAccel = LoadAccelerators (hInstance, "tstappaccel");
if (!hAccel)
return (FALSE);
/*
* Just use default size and location. It's easier to size an already
* created window for the specific client area size.
*/
hwndMain = CreateWindow ("Test App", WINDOW_NAME,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
if (!hwndMain)
return (FALSE);
ShowWindow (hwndMain, nCmdShow);
UpdateWindow (hwndMain);
hDC = GetDC (hwndMain);
if (GetDeviceCaps (hDC, RASTERCAPS) & RC_PALETTE)
{
uErrMode = SetErrorMode (SEM_NOOPENFILEERRORBOX);
#ifdef WIN32
hWinGInst = LoadLibrary ("wing32.dll");
#else
hWinGInst = LoadLibrary ("wing.dll");
if (hWinGInst < HINSTANCE_ERROR)
hWinGInst = 0;
#endif
SetErrorMode (uErrMode);
}
else
hWinGInst = NULL;
ReleaseDC (hwndMain, hDC);
hMenu = GetMenu (hwndMain);
#ifdef USE_WING
if (hWinGInst)
{
InitializeWinG ();
CheckMenuItem (hMenu, ID_OPTIONS_TC_DISPLAY_WING, MF_BYCOMMAND | MF_CHECKED);
CheckMenuItem (hMenu, ID_OPTIONS_TC_DISPLAY_IMGLIB, MF_BYCOMMAND | MF_UNCHECKED);
}
else
#endif
EnableMenuItem (hMenu, ID_OPTIONS_TC_DISPLAY_WING, MF_BYCOMMAND | MF_GRAYED);
return (TRUE);
}
/****************************************************************************
FUNCTION: MainWndProc(HWND, UINT, WPARAM, LPARAM)
PURPOSE: Processes messages
****************************************************************************/
LRESULT CALLBACK MainWndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int iCount, iBrightness;
static char szFileName[260], szOldTitle[256];
LPVOID lpDIBNew;
HMENU hMenu;
DWORD dwStartTime;
static short nFileType;
PRINTDLG PrintDlgStruct;
switch (message)
{
case WM_QUERYNEWPALETTE:
case WM_PALETTECHANGED:
case WM_PAINT:
return (HandlePaintingAndUpdates (message, wParam, lParam));
break;
case WM_CHAR:
HandleCharacter (wParam, lParam);
break;
case WM_LBUTTONDOWN:
HandleLButtonDown (wParam, lParam);
break;
case WM_RBUTTONDOWN:
HandleRButtonDown (wParam, lParam);
break;
case WM_LBUTTONUP:
HandleLButtonUp (wParam, lParam);
break;
case WM_MOUSEMOVE:
HandleMouseMove (wParam, lParam);
break;
case WM_INITMENUPOPUP:
HandleMenuPopup (wParam, lParam);
break;
case WM_VSCROLL:
HandleVerticalScroll (wParam, lParam);
break;
case WM_HSCROLL:
HandleHorizontalScroll (wParam, lParam);
break;
case WM_SIZE:
HandleWindowSizing (lpDIBDisplay, wParam, lParam);
break;
case WM_COMMAND:
switch (CONTROL_ID (wParam))
{
case ID_FILE_PRINT:
if (lpDIB1)
HandlePrinting (lpDIB1);
break;
case ID_FILE_PRINT_SETUP:
if (!pPrintDlgStruct)
InitializePrintStruct ();
if (!pPrintDlgStruct)
break;
PrintDlgStruct = *pPrintDlgStruct;
PrintDlgStruct.hwndOwner = hWnd;
PrintDlgStruct.Flags = PD_PRINTSETUP;
if (PrintDlg (&PrintDlgStruct) == TRUE)
*pPrintDlgStruct = PrintDlgStruct;
break;
case ID_FILE_SAVE:
if (lpDIB1)
{
if (GetSaveFile (szFileName) == FALSE)
break;
if (DialogBoxParam (hInst, "IDD_FILETYPE", hWnd, FileTypeProc, (LPARAM)(LPINT)&nFileType) != TRUE)
break;
UpdateWindowTitle (szFileName, TRUE);
if (WriteDIBToFile (lpDIB1, szFileName, nFileType) == FALSE)
{
switch (GetLastImgLibError ())
{
case ERROR_WRITE_ACCESS_DENIED:
wsprintf ((LPSTR)szBuffer, (LPSTR)"Error writing to file \"%s\"", (LPSTR)szFileName);
break;
case ERROR_INVALID_POINTER:
wsprintf ((LPSTR)szBuffer, (LPSTR)"Error accessing one of the pointer parameters", (LPSTR)szFileName);
break;
case ERROR_INCOMPATIBLE_IMAGE:
wsprintf ((LPSTR)szBuffer, (LPSTR)"Image format incompatible with the selected file type", (LPSTR)szFileName);
break;
}
MessageBox (NULL, szBuffer, "Save Error", MB_TASKMODAL | MB_ICONSTOP | MB_OK);
}
}
break;
case ID_FILE_OPEN:
if (GetOpenFile (szFileName) == FALSE)
break;
SetCursor (LoadCursor (NULL, IDC_WAIT));
lpDIBNew = ReadFileIntoDIB (szFileName);
if (lpDIBNew)
{
bDrawSelection = FALSE;
UpdateWindowTitle (szFileName, TRUE);
ProcessNewDIB (lpDIBNew);;
}
SetCursor (LoadCursor (NULL, IDC_ARROW));
if (!lpDIBNew)
{
switch (GetLastImgLibError ())
{
case ERROR_UNSUPPORTED_IMAGE:
MessageBox (hWnd, "Unsupported image type", WINDOW_NAME, MB_OK | MB_ICONSTOP);
break;
case ERROR_NO_MEMORY:
MessageBox (hWnd, "Out of memory reading image", WINDOW_NAME, MB_OK | MB_ICONSTOP);
break;
case ERROR_INVALID_POINTER:
MessageBox (hWnd, "Access violation", WINDOW_NAME, MB_OK | MB_ICONSTOP);
break;
}
}
break;
case ID_OPTIONS_TIME:
if (GetOpenFile (szFileName) == FALSE)
break;
SetCursor (LoadCursor (NULL, IDC_WAIT));
GetWindowText (hWnd, szOldTitle, sizeof (szOldTitle));
dwStartTime = GetTickCount ();
for (iCount = 0;iCount < 10;iCount++)
{
wsprintf ((LPSTR)szBuffer, (LPSTR)"Testing image loading speed \"%s\" -- %d", (LPSTR)szFileName, iCount);
UpdateWindowTitle (szBuffer, FALSE);
lpDIBNew = ReadFileIntoDIB (szFileName);
if (lpDIBNew)
{
DIBFree (lpDIBNew);
}
else
{
break;
}
}
SetWindowText (hWnd, szOldTitle);
SetCursor (LoadCursor (NULL, IDC_ARROW));
if (iCount == 10)
wsprintf ((LPSTR)szBuffer, (LPSTR)"File \"%s\" loaded 10 times in %ld milliseconds", (LPSTR)szFileName, GetTickCount () - dwStartTime);
else
wsprintf ((LPSTR)szBuffer, (LPSTR)"File \"%s\" failed to load 10 times", (LPSTR)szFileName);
MessageBox (hWnd, szBuffer, "ImgLib Timing Results", MB_OK);
break;
case ID_FILE_EXIT:
DestroyWindow (hWnd);
break;
case ID_EDIT_UNDO:
if (lpDIB1 && lpDIB2)
{
SetCursor (LoadCursor (NULL, IDC_WAIT));
if (lpDIBDisplay && lpDIBDisplay != lpDIB1)
DIBFree (lpDIBDisplay);
lpDIBNew = lpDIB2;
lpDIB2 = lpDIB1;
lpDIB1 = lpDIBNew;
if (hPalette)
{
DeleteObject (hPalette);
hPalette = NULL;
}
lpDIBDisplay = CreateDisplayDIB (hWnd, &lpDIB1, &hPalette);
bDrawSelection = FALSE;
ResizeWindowToDIB (hWnd, lpDIBDisplay);
SetCursor (LoadCursor (NULL, IDC_ARROW));
}
break;
case ID_EDIT_PASTE:
HandlePasting (wParam, lParam);
break;
case ID_EDIT_COPY:
HandleCopying (wParam, lParam);
break;
case ID_EDIT_ZOOM:
HandleZoomin (wParam, lParam);
break;
case ID_EDIT_EMPTY:
if (OpenClipboard (hWnd))
{
EmptyClipboard ();
CloseClipboard ();
}
break;
case ID_PROCESS_BRIGHTNESS:
if (lpDIB1)
{
iBrightness = DialogBox (hInst, "IDD_BRIGHTNESS", hWnd, BrightnessProc);
if (iBrightness)
{
SetCursor (LoadCursor (NULL, IDC_WAIT));
lpDIBNew = BrightenDIB (lpDIB1, (short)iBrightness);
ProcessNewDIB (lpDIBNew);
SetCursor (LoadCursor (NULL, IDC_ARROW));
}
}
break;
case ID_PROCESS_SMOOTH:
if (lpDIB1)
{
SetCursor (LoadCursor (NULL, IDC_WAIT));
lpDIBNew = SmoothDIB (lpDIB1, 1);
ProcessNewDIB (lpDIBNew);
SetCursor (LoadCursor (NULL, IDC_ARROW));
}
break;
case ID_PROCESS_HALFTONE:
if (lpDIB1)
{
SetCursor (LoadCursor (NULL, IDC_WAIT));
lpDIBNew = HalftoneDIB (lpDIB1);
ProcessNewDIB (lpDIBNew);
SetCursor (LoadCursor (NULL, IDC_ARROW));
}
break;
case ID_PROCESS_GRAY:
if (lpDIB1)
{
SetCursor (LoadCursor (NULL, IDC_WAIT));
lpDIBNew = GrayDIB (lpDIB1);
ProcessNewDIB (lpDIBNew);
SetCursor (LoadCursor (NULL, IDC_ARROW));
}
break;
case ID_PROCESS_EXPAND:
if (lpDIB1)
{
SetCursor (LoadCursor (NULL, IDC_WAIT));
lpDIBNew = ExpandToTrueDIB (lpDIB1);
ProcessNewDIB (lpDIBNew);
SetCursor (LoadCursor (NULL, IDC_ARROW));
}
break;
case ID_PROCESS_ROT90:
case ID_PROCESS_ROT180:
case ID_PROCESS_ROT270:
if (lpDIB1)
{
SetCursor (LoadCursor (NULL, IDC_WAIT));
switch (CONTROL_ID (wParam))
{
case ID_PROCESS_ROT90:
lpDIBNew = RotateDIB (lpDIB1, 90);
break;
case ID_PROCESS_ROT180:
lpDIBNew = RotateDIB (lpDIB1, 180);
break;
case ID_PROCESS_ROT270:
lpDIBNew = RotateDIB (lpDIB1, 270);
break;
}
ProcessNewDIB (lpDIBNew);
SetCursor (LoadCursor (NULL, IDC_ARROW));
}
break;
case ID_PROCESS_MIRRORH:
case ID_PROCESS_MIRRORV:
if (lpDIB1)
{
SetCursor (LoadCursor (NULL, IDC_WAIT));
switch (CONTROL_ID (wParam))
{
case ID_PROCESS_MIRRORH:
lpDIBNew = MirrorDIB (lpDIB1, FALSE);
break;
case ID_PROCESS_MIRRORV:
lpDIBNew = MirrorDIB (lpDIB1, TRUE);
break;
}
ProcessNewDIB (lpDIBNew);
SetCursor (LoadCursor (NULL, IDC_ARROW));
}
break;
case ID_OPTIONS_TC_DISPLAY_GDI:
hMenu = GetMenu (hWnd);
CheckMenuItem (hMenu, ID_OPTIONS_TC_DISPLAY_GDI, MF_BYCOMMAND | MF_CHECKED);
CheckMenuItem (hMenu, ID_OPTIONS_TC_DISPLAY_WING, MF_BYCOMMAND | MF_UNCHECKED);
CheckMenuItem (hMenu, ID_OPTIONS_TC_DISPLAY_IMGLIB, MF_BYCOMMAND | MF_UNCHECKED);
if (lpDIB1)
{
if (lpDIBDisplay && lpDIBDisplay != lpDIB1)
DIBFree (lpDIBDisplay);
lpDIBDisplay = CreateDisplayDIB (hWnd, &lpDIB1, &hPalette);
InvalidateRect (hWnd, (LPRECT) (NULL), FALSE);
}
break;
case ID_OPTIONS_TC_DISPLAY_WING:
hMenu = GetMenu (hWnd);
CheckMenuItem (hMenu, ID_OPTIONS_TC_DISPLAY_GDI, MF_BYCOMMAND | MF_UNCHECKED);
CheckMenuItem (hMenu, ID_OPTIONS_TC_DISPLAY_WING, MF_BYCOMMAND | MF_CHECKED);
CheckMenuItem (hMenu, ID_OPTIONS_TC_DISPLAY_IMGLIB, MF_BYCOMMAND | MF_UNCHECKED);
if (lpDIB1)
{
SetCursor (LoadCursor (NULL, IDC_WAIT));
if (lpDIBDisplay && lpDIBDisplay != lpDIB1)
DIBFree (lpDIBDisplay);
lpDIBDisplay = CreateDisplayDIB (hWnd, &lpDIB1, &hPalette);
InvalidateRect (hWnd, (LPRECT) (NULL), FALSE);
SetCursor (LoadCursor (NULL, IDC_ARROW));
}
break;
case ID_OPTIONS_TC_DISPLAY_IMGLIB:
hMenu = GetMenu (hWnd);
CheckMenuItem (hMenu, ID_OPTIONS_TC_DISPLAY_GDI, MF_BYCOMMAND | MF_UNCHECKED);
CheckMenuItem (hMenu, ID_OPTIONS_TC_DISPLAY_WING, MF_BYCOMMAND | MF_UNCHECKED);
CheckMenuItem (hMenu, ID_OPTIONS_TC_DISPLAY_IMGLIB, MF_BYCOMMAND | MF_CHECKED);
if (lpDIB1)
{
SetCursor (LoadCursor (NULL, IDC_WAIT));
if (lpDIBDisplay && lpDIBDisplay != lpDIB1)
DIBFree (lpDIBDisplay);
lpDIBDisplay = CreateDisplayDIB (hWnd, &lpDIB1, &hPalette);
InvalidateRect (hWnd, (LPRECT) (NULL), FALSE);
SetCursor (LoadCursor (NULL, IDC_ARROW));
}
break;
case ID_OPTIONS_RETAIN_TC:
hMenu = GetMenu (hWnd);
if (GetMenuState (hMenu, ID_OPTIONS_RETAIN_TC, MF_BYCOMMAND) & MF_CHECKED)
{
CheckMenuItem (hMenu, ID_OPTIONS_RETAIN_TC, MF_BYCOMMAND | MF_UNCHECKED);
if (lpDIBDisplay && lpDIB1 != lpDIBDisplay)
{
DIBFree (lpDIB1);
lpDIB1 = lpDIBDisplay;
}
}
else
{
CheckMenuItem (hMenu, ID_OPTIONS_RETAIN_TC, MF_BYCOMMAND | MF_CHECKED);
}
break;
case ID_HELP_ABOUT:
DialogBox (hInst, "IDD_ABOUT_DIALOG", hWnd, AboutProc);
break;
default:
return (DefWindowProc (hWnd, message, wParam, lParam));
}
break;
case WM_DESTROY:
if (lpDIB1)
DIBFree (lpDIB1);
if (lpDIB2)
DIBFree (lpDIB2);
if (lpDIBDisplay && lpDIBDisplay != lpDIB1)
DIBFree (lpDIBDisplay);
if (hPalette)
{
DeleteObject (hPalette);
hPalette = NULL;
}
if (hWinGInst)
{
if (hbmpWinG)
{
SelectObject (hdcWinG, hbmpWinGOld);
DeleteObject (hbmpWinG);
}
DeleteDC (hdcWinG);
FreeLibrary (hWinGInst);
}
PostQuitMessage(0);
break;
default:
return (DefWindowProc (hWnd, message, wParam, lParam));
}
return (0);
}
/****************************************************************************
FUNCTION: AboutProc(HWND, UINT, WPARAM, LPARAM)
PURPOSE: Processes messages for the About dialog
****************************************************************************/
BOOL CALLBACK AboutProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
HWND hwndStatic;
char szImgLibVer[512];
switch (message)
{
case WM_INITDIALOG:
hwndStatic = GetDlgItem (hDlg, IDC_ABOUT_STRING);
GetImgLibVersion (szImgLibVer, sizeof (szImgLibVer));
SetWindowText (hwndStatic, szImgLibVer);
return (TRUE);
case WM_COMMAND:
if (CONTROL_ID (wParam) == IDOK)
{
EndDialog(hDlg, TRUE);
return (TRUE);
}
break;
}
return (FALSE);
}
/****************************************************************************
FUNCTION: BrightnessProc(HWND, UINT, WPARAM, LPARAM)
PURPOSE: Processes messages for the Brightness Control dialog
****************************************************************************/
BOOL CALLBACK BrightnessProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
HWND hwndStatic, hwndScroll;
char szMessage[32];
int iScrollCode, iNewPos;
static LPVOID lpDIBSave;
LPVOID lpDIBNew;
switch (message)
{
case WM_INITDIALOG:
lpDIBSave = lpDIBDisplay;
hwndScroll = GetDlgItem (hDlg, IDC_BRIGHTNESS_SCROLLBAR);
SetScrollRange (hwndScroll, SB_CTL, 50, 150, TRUE);
SetScrollPos (hwndScroll, SB_CTL, 100, TRUE);
return (TRUE);
case WM_HSCROLL:
#ifdef WIN32
iScrollCode = (int) LOWORD (wParam);
iNewPos = (int) HIWORD (wParam);
#else
iScrollCode = (int) wParam;
iNewPos = (int) LOWORD (lParam);
#endif
hwndScroll = GetDlgItem (hDlg, IDC_BRIGHTNESS_SCROLLBAR);
switch (iScrollCode)
{
case SB_ENDSCROLL:
iNewPos = GetScrollPos (hwndScroll, SB_CTL);
lpDIBNew = BrightenDIB (lpDIBSave, (short) iNewPos);
if (lpDIBNew)
{
if (lpDIBDisplay != lpDIBSave)
DIBFree (lpDIBDisplay);
lpDIBDisplay = lpDIBNew;
InvalidateRect (hwndMain, NULL, FALSE);
}
break;
case SB_LINEDOWN:
iNewPos = GetScrollPos (hwndScroll, SB_CTL) + 1;
break;
case SB_LINEUP:
iNewPos = GetScrollPos (hwndScroll, SB_CTL) - 1;
break;
case SB_PAGEDOWN:
iNewPos = GetScrollPos (hwndScroll, SB_CTL) + 10;
break;
case SB_PAGEUP:
iNewPos = GetScrollPos (hwndScroll, SB_CTL) - 10;
break;
}
if (iNewPos < 50)
iNewPos = 50;
if (iNewPos > 150)
iNewPos = 150;
wsprintf ((LPSTR)szMessage, (LPSTR)"%d %%", iNewPos);
hwndStatic = GetDlgItem (hDlg, IDC_BRIGHTNESS_PERCENTAGE);
SetWindowText (hwndStatic, szMessage);
SetScrollPos (hwndScroll, SB_CTL, iNewPos, TRUE);
return (TRUE);
case WM_COMMAND:
switch (CONTROL_ID (wParam))
{
case IDOK:
hwndScroll = GetDlgItem (hDlg, IDC_BRIGHTNESS_SCROLLBAR);
iNewPos = GetScrollPos (hwndScroll, SB_CTL);
if (lpDIBDisplay != lpDIBSave)
{
DIBFree (lpDIBDisplay);
lpDIBDisplay = lpDIBSave;
}
EndDialog(hDlg, iNewPos);
return (TRUE);
case IDCANCEL:
if (lpDIBDisplay != lpDIBSave)
{
DIBFree (lpDIBDisplay);
lpDIBDisplay = lpDIBSave;
InvalidateRect (hwndMain, NULL, FALSE);
}
EndDialog(hDlg, FALSE);
return (TRUE);
}
break;
}
return (FALSE);
}
/****************************************************************************
FUNCTION: FileTypeProc(HWND, UINT, WPARAM, LPARAM)
PURPOSE: Processes messages for the FileType dialog
****************************************************************************/
BOOL CALLBACK FileTypeProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
static short *pnFileType;
int iCtrl;
switch (message)
{
case WM_INITDIALOG:
pnFileType = (short *)lParam;
switch (*pnFileType)
{
case FILETYPE_BMP:
iCtrl = IDC_IT_BMP;
break;
case FILETYPE_TIFF_DEFAULT:
iCtrl = IDC_IT_TIFF;
break;
case FILETYPE_TIFF_NO_COMPRESSION:
iCtrl = IDC_IT_TIFF_NOCOMP;
break;
case FILETYPE_TIFF_HUFFMAN:
iCtrl = IDC_IT_TIFF_HUFFMAN;
break;
case FILETYPE_TIFF_PACKBITS:
iCtrl = IDC_IT_TIFF_PACKBITS;
break;
case FILETYPE_TIFF_G3:
iCtrl = IDC_IT_TIFF_G3;
break;
case FILETYPE_TIFF_G4:
iCtrl = IDC_IT_TIFF_G4;
break;
default:
iCtrl = IDC_IT_BMP;
break;
}
CheckRadioButton (hDlg, IDC_IT_BMP, IDC_IT_TIFF_G4, iCtrl);
return (TRUE);
case WM_COMMAND:
if (CONTROL_ID (wParam) == IDOK)
{
if (IsDlgButtonChecked (hDlg, IDC_IT_BMP))
*pnFileType = FILETYPE_BMP;
else if (IsDlgButtonChecked (hDlg, IDC_IT_TIFF))
*pnFileType = FILETYPE_TIFF_DEFAULT;
else if (IsDlgButtonChecked (hDlg, IDC_IT_TIFF_NOCOMP))
*pnFileType = FILETYPE_TIFF_NO_COMPRESSION;
else if (IsDlgButtonChecked (hDlg, IDC_IT_TIFF_HUFFMAN))
*pnFileType = FILETYPE_TIFF_HUFFMAN;
else if (IsDlgButtonChecked (hDlg, IDC_IT_TIFF_PACKBITS))
*pnFileType = FILETYPE_TIFF_PACKBITS;
else if (IsDlgButtonChecked (hDlg, IDC_IT_TIFF_G3))
*pnFileType = FILETYPE_TIFF_G3;
else if (IsDlgButtonChecked (hDlg, IDC_IT_TIFF_G4))
*pnFileType = FILETYPE_TIFF_G4;
EndDialog(hDlg, TRUE);
return (TRUE);
}
else if (CONTROL_ID (wParam) == IDCANCEL)
{
EndDialog(hDlg, FALSE);
return (TRUE);
}
break;
}
return (FALSE);
}
/****************************************************************************
FUNCTION: PrintProc(HWND, UINT, WPARAM, LPARAM)
PURPOSE: Processes messages for the Print dialog
****************************************************************************/
BOOL CALLBACK PrintProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
static LPBITMAPINFOHEADER pBmi;
HWND hwndCtl;
LPDEVNAMES pDevNames, pDevNamesNew;
LPDEVMODE pDevMode, pDevModeNew;
char szBuffer[256];
static PRINTDLG PrintDlgStruct;
unsigned int uCopyCount;
BOOL bConvertOK;
HANDLE hDevModeNew, hDevNamesNew;
switch (message)
{
case WM_INITDIALOG:
PrintDlgStruct = *pPrintDlgStruct;
SetDlgItemInt (hDlg, IDC_COPY_COUNT, uPrintCopies, FALSE);
pBmi = (LPBITMAPINFOHEADER) lParam;
pDevNames = (LPDEVNAMES)GlobalLock (pPrintDlgStruct->hDevNames);
pDevMode = (LPDEVMODE)GlobalLock (pPrintDlgStruct->hDevMode);
/*
* Make copies of the DEVNAMES and DEVMODE structures
*/
hDevNamesNew = GlobalAlloc (GMEM_MOVEABLE, GlobalSize (pPrintDlgStruct->hDevNames));
pDevNamesNew = (LPDEVNAMES) GlobalLock (hDevNamesNew);
hDevModeNew = GlobalAlloc (GMEM_MOVEABLE, GlobalSize (pPrintDlgStruct->hDevMode));
pDevModeNew = (LPDEVMODE) GlobalLock (hDevModeNew);
copymem (pDevModeNew, pDevMode, GlobalSize (hDevModeNew));
copymem (pDevNamesNew, pDevNames, GlobalSize (hDevNamesNew));
GlobalUnlock (pPrintDlgStruct->hDevNames);
GlobalUnlock (pPrintDlgStruct->hDevMode);
PrintDlgStruct.hDevMode = hDevModeNew;
PrintDlgStruct.hDevNames = hDevNamesNew;
if (pBmi->biPlanes * pBmi->biBitCount == 1 || pDevModeNew->dmColor == DMCOLOR_COLOR) // monochrome bitmap or color printer
{
hwndCtl = GetDlgItem (hDlg, IDC_HALFTONE_GROUP);
EnableWindow (hwndCtl, FALSE);
hwndCtl = GetDlgItem (hDlg, IDC_METHOD_GDI);
EnableWindow (hwndCtl, FALSE);
hwndCtl = GetDlgItem (hDlg, IDC_METHOD_IMGLIB);
EnableWindow (hwndCtl, FALSE);
}
else
{
if (bHalftoneImgLib)
CheckRadioButton (hDlg, IDC_METHOD_GDI, IDC_METHOD_IMGLIB, IDC_METHOD_IMGLIB);
else
CheckRadioButton (hDlg, IDC_METHOD_GDI, IDC_METHOD_IMGLIB, IDC_METHOD_GDI);
}
if (bFillPage)
CheckDlgButton (hDlg, IDC_FILL_PAGE, TRUE);
wsprintf ((LPSTR)szBuffer, (LPSTR)"%s on %s", (LPSTR)pDevNamesNew + pDevNamesNew->wDeviceOffset, (LPSTR)pDevNamesNew + pDevNamesNew->wOutputOffset);
SetDlgItemText (hDlg, IDC_PRINTERNAME, szBuffer);
GlobalUnlock (hDevNamesNew);
GlobalUnlock (hDevModeNew);
return (TRUE);
case WM_COMMAND:
switch (CONTROL_ID (wParam))
{
case IDC_SETUP_PRINTER:
PrintDlgStruct.hwndOwner = hDlg;
PrintDlgStruct.Flags = PD_PRINTSETUP;
if (PrintDlg (&PrintDlgStruct))
{
pDevModeNew = (LPDEVMODE) GlobalLock (PrintDlgStruct.hDevMode);
if (pBmi->biPlanes * pBmi->biBitCount == 1 || pDevModeNew->dmColor == DMCOLOR_COLOR) // monochrome bitmap or color printer
{
hwndCtl = GetDlgItem (hDlg, IDC_HALFTONE_GROUP);
EnableWindow (hwndCtl, FALSE);
hwndCtl = GetDlgItem (hDlg, IDC_METHOD_GDI);
EnableWindow (hwndCtl, FALSE);
hwndCtl = GetDlgItem (hDlg, IDC_METHOD_IMGLIB);
EnableWindow (hwndCtl, FALSE);
}
else
{
hwndCtl = GetDlgItem (hDlg, IDC_HALFTONE_GROUP);
EnableWindow (hwndCtl, TRUE);
hwndCtl = GetDlgItem (hDlg, IDC_METHOD_GDI);
EnableWindow (hwndCtl, TRUE);
hwndCtl = GetDlgItem (hDlg, IDC_METHOD_IMGLIB);
EnableWindow (hwndCtl, TRUE);
}
GlobalUnlock (PrintDlgStruct.hDevMode);
}
return (TRUE);
case IDOK:
uCopyCount = GetDlgItemInt (hDlg, IDC_COPY_COUNT, &bConvertOK, FALSE);
if (!bConvertOK || uCopyCount < 1 || uCopyCount > 100)
{
MessageBox (hDlg, "Invalid value. Please enter a number between 1 and 100", "Print", MB_ICONSTOP | MB_OK);
SetFocus (GetDlgItem (hDlg, IDC_COPY_COUNT));
return (TRUE);
}
uPrintCopies = uCopyCount;
bFillPage = IsDlgButtonChecked (hDlg, IDC_FILL_PAGE);
bHalftoneImgLib = IsDlgButtonChecked (hDlg, IDC_METHOD_IMGLIB);
GlobalFree (pPrintDlgStruct->hDevNames);
GlobalFree (pPrintDlgStruct->hDevMode);
*pPrintDlgStruct = PrintDlgStruct;
EndDialog (hDlg, TRUE);
return (TRUE);
case IDCANCEL:
GlobalFree (PrintDlgStruct.hDevNames);
GlobalFree (PrintDlgStruct.hDevMode);
EndDialog (hDlg, FALSE);
return (TRUE);
}
break;
}
return (FALSE);
}
/*************************************************************************
Function: GetOpenFile (LPSTR. WORD)
Purpose: Prompts user for a filename through the use of a Windows
FileOpen common dialog box.
Returns: TRUE if a filename is selected.
FALSE if no filename is selected.
Comments: Filename is put into the string passed to the routine.
If a filename is not selected, NULL is returned.
*************************************************************************/
BOOL GetOpenFile (LPSTR szFileName)
{
OPENFILENAME of;
DWORD flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST;
static char szTitle[30]; // Dialog Box title
static char szTemplate[20]; // Dialog Box template
static char szFile[256]; // File name
static char szFileTitle[256]; // Title
static char szDrive[5]; // Drive
static char szDir[256]; // Directory
char szFilter[] = // Filter
"Pictures\0*.bmp;*.jpg;*.tga;*.pcd;*.pcx;*.tif\0All Files\0*.*\0";
LPSTR pFile;
szFile[0] = '\0';
of.lStructSize = sizeof (OPENFILENAME);
of.hwndOwner = hwndMain;
of.hInstance = hInst;
of.lpstrFilter = szFilter;
of.lpstrCustomFilter = NULL;
of.nMaxCustFilter = 0L;
of.nFilterIndex = 1L;
of.lpstrFile = szFile;
of.nMaxFile = sizeof (szFile);
of.lpstrFileTitle = szFileTitle;
of.nMaxFileTitle = sizeof (szFileTitle);
of.lpstrInitialDir = szDir;
of.lpstrTitle = "Open a new test bitmap file";
of.Flags = flags;
of.nFileOffset = 0;
of.nFileExtension = 0;
of.lpstrDefExt = NULL;
of.lCustData = 0;
of.lpfnHook = NULL;
of.lpTemplateName = NULL;
if (GetOpenFileName (&of))
{
lstrcpy (szFileName, of.lpstrFile);
lstrcpy (szDir, of.lpstrFile);
pFile = strrchr (szDir, '\\');
if (pFile)
*pFile = 0;
return TRUE;
}
else
return FALSE;
}
/*************************************************************************
Function: GetSaveFile (LPSTR. WORD)
Purpose: Prompts user for a filename through the use of a Windows
FileOpen common dialog box.
Returns: TRUE if a filename is selected.
FALSE if no filename is selected.
Comments: Filename is put into the string passed to the routine.
If a filename is not selected, NULL is returned.
*************************************************************************/
BOOL GetSaveFile (LPSTR szFileName)
{
OPENFILENAME of;
DWORD flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT;
static char szTitle[30]; // Dialog Box title
static char szTemplate[20]; // Dialog Box template
static char szFile[256]; // File name
static char szFileTitle[256]; // Title
static char szDrive[5]; // Drive
static char szDir[256]; // Directory
char szFilter[] = // Filter
"Windows Pictures\0*.bmp;*.tif\0All Files\0*.*\0";
LPSTR pFile;
szFile[0] = '\0';
of.lStructSize = sizeof (OPENFILENAME);
of.hwndOwner = GetFocus ();
of.hInstance = hInst;
of.lpstrFilter = szFilter;
of.lpstrCustomFilter = NULL;
of.nMaxCustFilter = 0L;
of.nFilterIndex = 1L;
of.lpstrFile = szFile;
of.nMaxFile = sizeof (szFile);
of.lpstrFileTitle = szFileTitle;
of.nMaxFileTitle = sizeof (szFileTitle);
of.lpstrInitialDir = szDir;
of.lpstrTitle = "Save the image in a bitmap file";
of.Flags = flags;
of.nFileOffset = 0;
of.nFileExtension = 0;
of.lpstrDefExt = "*.bmp";
of.lCustData = 0;
of.lpfnHook = NULL;
of.lpTemplateName = NULL;
if (GetSaveFileName (&of))
{
lstrcpy (szFileName, of.lpstrFile);
lstrcpy (szDir, of.lpstrFile);
pFile = strrchr (szDir, '\\');
if (pFile)
*pFile = 0;
return TRUE;
}
else
return FALSE;
}
/*************************************************************************
Function: CreateDisplayDIB()
Purpose: Creates a DIB suitable for the display based on user-selected options.
Returns: a new DIB pointer
*************************************************************************/
LPVOID CreateDisplayDIB (HWND hwnd, LPVOID *lpDIB, HPALETTE *phPal)
{
HMENU hMenu;
LPBITMAPINFO pBitmapInfo;
UINT uState;
LPVOID lpDIBDisplay;
long lColors;
int iPixelBits, iPlanes;
HDC hDC;
hDC = GetDC (hwnd);
iPixelBits = GetDeviceCaps (hDC, BITSPIXEL);
iPlanes = GetDeviceCaps (hDC, PLANES);
ReleaseDC (hwnd, hDC);
if (iPixelBits * iPlanes > 8)
{
/*
* No color reduction on true color (or high color) displays
*/
*phPal = NULL;
return (*lpDIB);
}
pBitmapInfo = (LPBITMAPINFO) *lpDIB;
hMenu = GetMenu (hwnd);
uState = GetMenuState (hMenu, ID_OPTIONS_TC_DISPLAY_GDI, MF_BYCOMMAND);
if (uState & MF_CHECKED || pBitmapInfo->bmiHeader.biClrUsed)
{
lpDIBDisplay = *lpDIB;
if (pBitmapInfo->bmiHeader.biClrUsed > 2)
*phPal = CreateDIBPalette (lpDIBDisplay);
else
*phPal = NULL;
}
else
{
uState = GetMenuState (hMenu, ID_OPTIONS_TC_DISPLAY_WING, MF_BYCOMMAND);
if (uState & MF_CHECKED && hWinGInst)
{
lpDIBDisplay = WinGHalftoneDIB (*lpDIB, phPal);
}
else
{
lColors = 1 << iPixelBits * iPlanes;
lpDIBDisplay = ReduceDIB (*lpDIB, lColors, TRUE);
*phPal = CreateDIBPalette (lpDIBDisplay);
}
if (lpDIBDisplay && lpDIBDisplay != *lpDIB)
{
if (!(GetMenuState (hMenu, ID_OPTIONS_RETAIN_TC, MF_BYCOMMAND) & MF_CHECKED))
{
DIBFree (*lpDIB);
*lpDIB = lpDIBDisplay;
}
}
}
#ifdef USE_WING
/*
* Use WinG for displaying if available
*/
if (hWinGInst)
UpdateWinGBitmap (lpDIBDisplay);
#endif
return (lpDIBDisplay);
}
/*************************************************************************
Function: UpdateWindowTitle ()
Purpose: Updates the window title with the name of the file displayed.
Returns: none
*************************************************************************/
static void UpdateWindowTitle (LPSTR pszFilePath, BOOL bStripPath)
{
static char szWindowName[260];
char szFileName[260];
char *pszFileName = NULL;
if (pszFilePath && *pszFilePath)
{
/*
* Make local copy because in 16-bit world strrchr can only operate on
* near pointers.
*/
lstrcpy (szFileName, pszFilePath);
if (bStripPath)
pszFileName = strrchr (szFileName, '\\');
/*
* If found the last path delimiter, skip over it.
*/
if (pszFileName)
pszFileName++;
else
pszFileName = szFileName;
wsprintf ((LPSTR)szWindowName, (LPSTR)"%s -- %s", (LPSTR)WINDOW_NAME, (LPSTR)pszFileName);
}
else
wsprintf ((LPSTR)szWindowName, (LPSTR)"%s", (LPSTR)WINDOW_NAME);
SetWindowText (hwndMain, szWindowName);
}
/*************************************************************************
Function: ResizeWindowToDIB ()
Purpose: Updates the window size to fit the given device-independent DIB
Returns: none
*************************************************************************/
static void ResizeWindowToDIB (HWND hwnd, LPVOID pDIB)
{
int iWidth, iHeight, iXOverhead, iYOverhead;
int iScreenWidth, iScreenHeight, iXPos, iYPos;
int iHScrollRange, iVScrollRange;
LPBITMAPINFOHEADER pBmi = (LPBITMAPINFOHEADER)pDIB;
HDC hDC;
RECT rect;
BOOL bHScroll, bVScroll;
DWORD dwStyle;
bHScroll = bVScroll = FALSE;
GetWindowRect (hwnd, &rect);
iXPos = rect.left;
if (iXPos < 0)
iXPos = 0;
iYPos = rect.top;
if (iYPos < 0)
iYPos = 0;
hDC = GetDC (hwnd);
iScreenWidth = GetDeviceCaps (hDC, HORZRES);
iScreenHeight = GetDeviceCaps (hDC, VERTRES);
ReleaseDC (hwnd, hDC);
iWidth = (int)pBmi->biWidth;
iHeight = (int)pBmi->biHeight;
iXOverhead = GetSystemMetrics (SM_CXFRAME) * 2;
iYOverhead = GetSystemMetrics (SM_CYFRAME) * 2 + GetSystemMetrics (SM_CYCAPTION) + GetSystemMetrics (SM_CYMENU);
if (iWidth + iXOverhead + iXPos > iScreenWidth)
{
iXPos = iScreenWidth - iWidth - iXOverhead;
if (iXPos < 0)
{
iHScrollRange = -iXPos;
iXPos = 0;
bHScroll = TRUE;
}
}
if (iHeight + iYOverhead + iYPos > iScreenHeight)
{
iYPos = iScreenHeight - iHeight - iYOverhead;
if (iYPos < 0)
{
iVScrollRange = -iYPos;
iYPos = 0;
bVScroll = TRUE;
}
}
dwStyle = GetWindowLong (hwnd, GWL_STYLE);
if (bHScroll)
{
ShowScrollBar (hwndMain, SB_HORZ, TRUE);
/*
* Having the vertical scrollbar will "steal" some more pixels
* from the client area. Check and adjust for it here.
*/
if (bVScroll)
iHScrollRange += GetSystemMetrics (SM_CXVSCROLL);
}
else
{
/*
* Remove the scrollbar
*/
if (dwStyle & WS_HSCROLL)
{
SetScrollPos (hwnd, SB_HORZ, 0, TRUE);
ShowScrollBar (hwndMain, SB_HORZ, FALSE);
}
}
if (bVScroll)
{
ShowScrollBar (hwndMain, SB_VERT, TRUE);
/*
* Having the horizontal scrollbar will "steal" some more pixels
* from the client area. Check and adjust for it here.
*/
if (bHScroll)
iVScrollRange += GetSystemMetrics (SM_CYHSCROLL);
}
else
{
/*
* Remove the scrollbar
*/
if (dwStyle & WS_VSCROLL)
{
SetScrollPos (hwnd, SB_VERT, 0, TRUE);
ShowScrollBar (hwndMain, SB_VERT, FALSE);
}
}
/*
* Having done all this checking, the following call may still cause the
* addition of scrollbars in rare circumstances like the menu bar becoming
* 2-line.
*/
SetWindowPos (hwnd, HWND_TOP, iXPos, iYPos, min (iXOverhead + iWidth, iScreenWidth),
min (iYOverhead + iHeight, iScreenHeight),
SWP_NOACTIVATE | SWP_NOZORDER);
if (bHScroll)
SetScrollRange (hwnd, SB_HORZ, 0, iHScrollRange, TRUE);
if (bVScroll)
SetScrollRange (hwnd, SB_VERT, 0, iVScrollRange, TRUE);
InvalidateRect (hwnd, (LPRECT) (NULL), FALSE);
}
/*************************************************************************
Function: HandleVerticalScroll ()
Purpose: Process the vertical scrollbar operations.
Returns: none
*************************************************************************/
static void HandleVerticalScroll (WPARAM wParam, LPARAM lParam)
{
int nScrollCode, iNewPos, iVScroll, iHScroll;
int iCurrPos, iMinScroll, iMaxScroll, iClientHeight;
RECT rect;
UpdateWindow (hwndMain);
#ifdef WIN32
nScrollCode = (int) LOWORD (wParam);
iNewPos = (int) HIWORD (wParam);
#else
nScrollCode = (int) wParam;
iNewPos = (int) LOWORD (lParam);
#endif
GetClientRect (hwndMain, &rect);
iClientHeight = rect.bottom;
iHScroll = iVScroll = 0;
GetScrollRange (hwndMain, SB_VERT, &iMinScroll, &iMaxScroll);
iCurrPos = GetScrollPos (hwndMain, SB_VERT);
switch (nScrollCode)
{
case SB_BOTTOM:
iVScroll = iMaxScroll - iCurrPos;
break;
case SB_PAGEDOWN:
if (iCurrPos + iClientHeight <= iMaxScroll)
iVScroll = -iClientHeight;
else
iVScroll = - (iMaxScroll - iCurrPos);
break;
case SB_PAGEUP:
if (iCurrPos - iClientHeight >= 0)
iVScroll = iClientHeight;
else
iVScroll = iCurrPos;
break;
case SB_THUMBTRACK:
case SB_THUMBPOSITION:
iVScroll = GetScrollPos (hwndMain, SB_VERT) - iNewPos;
break;
case SB_LINEDOWN:
iVScroll = -1;
break;
case SB_LINEUP:
iVScroll = 1;
break;
case SB_ENDSCROLL:
return;
}
if (iCurrPos - iVScroll > iMaxScroll)
iVScroll = iCurrPos - iMaxScroll;
if (iCurrPos - iVScroll < iMinScroll)
iVScroll = iCurrPos - iMinScroll;
if (!iVScroll)
return;
ScrollWindow (hwndMain, iHScroll, iVScroll, NULL, &rect);
SetScrollPos (hwndMain, SB_VERT, iCurrPos - iVScroll, TRUE);
}
/*************************************************************************
Function: HandleHorizontalScroll ()
Purpose: Process the horozontal scrollbar operations.
Returns: none
*************************************************************************/
static void HandleHorizontalScroll (WPARAM wParam, LPARAM lParam)
{
int nScrollCode, iNewPos, iVScroll, iHScroll;
int iCurrPos, iMinScroll, iMaxScroll, iClientWidth;
RECT rect;
UpdateWindow (hwndMain);
#ifdef WIN32
nScrollCode = (int) LOWORD (wParam);
iNewPos = (int) HIWORD (wParam);
#else
nScrollCode = (int) wParam;
iNewPos = (int) LOWORD (lParam);
#endif
GetClientRect (hwndMain, &rect);
iClientWidth = rect.right;
iHScroll = iVScroll = 0;
GetScrollRange (hwndMain, SB_HORZ, &iMinScroll, &iMaxScroll);
iCurrPos = GetScrollPos (hwndMain, SB_HORZ);
switch (nScrollCode)
{
case SB_BOTTOM:
iHScroll = iMaxScroll - iCurrPos;
break;
case SB_PAGEDOWN:
if (iCurrPos + iClientWidth <= iMaxScroll)
iHScroll = -iClientWidth;
else
iHScroll = - (iMaxScroll - iCurrPos);
break;
case SB_PAGEUP:
if (iCurrPos - iClientWidth >= 0)
iHScroll = iClientWidth;
else
iHScroll = iCurrPos;
break;
case SB_THUMBTRACK:
case SB_THUMBPOSITION:
iHScroll = GetScrollPos (hwndMain, SB_HORZ) - iNewPos;
break;
case SB_LINEDOWN:
iHScroll = -1;
break;
case SB_LINEUP:
iHScroll = 1;
break;
case SB_ENDSCROLL:
return;
}
if (iCurrPos - iHScroll > iMaxScroll)
iHScroll = iCurrPos - iMaxScroll;
if (iCurrPos - iHScroll < iMinScroll)
iHScroll = iCurrPos - iMinScroll;
if (!iHScroll)
return;
ScrollWindow (hwndMain, iHScroll, iVScroll, NULL, &rect);
SetScrollPos (hwndMain, SB_HORZ, iCurrPos - iHScroll, TRUE);
}
/*************************************************************************
Function: HandleWindowSizing ()
Purpose: Process the WM_SIZE messages.
Returns: none
*************************************************************************/
static void HandleWindowSizing (LPVOID pDIB, WPARAM wParam, LPARAM lParam)
{
LPBITMAPINFOHEADER pBmi = (LPBITMAPINFOHEADER)pDIB;
BOOL bHScroll, bVScroll;
DWORD dwStyle;
int iNewWidth, iNewHeight;
int iHScrollRange, iVScrollRange;
int iPos;
static BOOL bSizing;
/*
* Prevent resizing from infinitely recursing. This may be caused by having
* to add or take away a scrollbar which in turn causes another WM_SIZE
* message to be generated as the client area is affected by the scrollbars.
*/
if (bSizing)
return;
if (!pBmi)
return;
if (wParam == SIZE_MINIMIZED || wParam == SIZE_MAXHIDE || wParam == SIZE_MAXSHOW)
return;
bSizing = TRUE;
bHScroll = bVScroll = FALSE;
iHScrollRange = iVScrollRange = 0;
dwStyle = GetWindowLong (hwndMain, GWL_STYLE);
iNewWidth = (int) LOWORD (lParam);
iNewHeight = (int) HIWORD (lParam);
if (dwStyle & WS_HSCROLL)
iNewHeight += GetSystemMetrics (SM_CYHSCROLL);
if (dwStyle & WS_VSCROLL)
iNewWidth += GetSystemMetrics (SM_CXVSCROLL);
/*
* The following code determines if the scrollbars are required.
* Adding a scrollbar "steals" pixels from client area, so the affected
* dimension must be rechecked for a need of scrollbar.
*/
if (pBmi->biWidth > iNewWidth)
{
bHScroll = TRUE;
iHScrollRange = (int)pBmi->biWidth - iNewWidth;
iNewHeight -= GetSystemMetrics (SM_CYHSCROLL);
}
if (pBmi->biHeight > iNewHeight)
{
bVScroll = TRUE;
iVScrollRange = (int)pBmi->biHeight - iNewHeight;
iNewWidth -= GetSystemMetrics (SM_CXVSCROLL);
/*
* Recheck the width to see if a horizontal scrollbar may be ncecessary.
*/
if (pBmi->biWidth > iNewWidth && !bHScroll)
{
bHScroll = TRUE;
iHScrollRange = (int)pBmi->biWidth - iNewWidth;
iNewHeight -= GetSystemMetrics (SM_CYHSCROLL);
iVScrollRange += GetSystemMetrics (SM_CYHSCROLL);
}
}
if (!bHScroll && (dwStyle & WS_HSCROLL))
{
/*
* Remove the scrollbar
*/
SetScrollPos (hwndMain, SB_HORZ, 0, TRUE);
ShowScrollBar (hwndMain, SB_HORZ, FALSE);
}
if (!bVScroll && (dwStyle & WS_VSCROLL))
{
/*
* Remove the scrollbar
*/
SetScrollPos (hwndMain, SB_VERT, 0, TRUE);
ShowScrollBar (hwndMain, SB_VERT, FALSE);
}
/*
* Update the scrollbar positions and ranges
*/
if (bHScroll)
{
ShowScrollBar (hwndMain, SB_HORZ, TRUE);
iPos = GetScrollPos (hwndMain, SB_HORZ);
if (iPos > iHScrollRange)
{
InvalidateRect (hwndMain, NULL, FALSE);
SetScrollPos (hwndMain, SB_HORZ, iHScrollRange, TRUE);
}
SetScrollRange (hwndMain, SB_HORZ, 0, iHScrollRange, TRUE);
}
if (bVScroll)
{
ShowScrollBar (hwndMain, SB_VERT, TRUE);
iPos = GetScrollPos (hwndMain, SB_VERT);
if (iPos > iVScrollRange)
{
InvalidateRect (hwndMain, NULL, FALSE);
SetScrollPos (hwndMain, SB_VERT, iVScrollRange, TRUE);
}
SetScrollRange (hwndMain, SB_VERT, 0, iVScrollRange, TRUE);
}
bSizing = FALSE;
}
/*************************************************************************
Function: HandlePrinting ()
Purpose: Process the File/Print request.
Returns: none
*************************************************************************/
static void HandlePrinting (LPVOID lpDIB)
{
HDC hDC;
LPDEVNAMES pDevNames;
LPDEVMODE pDevMode;
LPVOID lpDIBPrint = NULL;
LPBITMAPINFOHEADER pBih;
LPBITMAPINFO pBmi;
char szTitle[128];
DOCINFO DocInfo;
int iXMargin, iYMargin, iWidth, iHeight;
if (!pPrintDlgStruct)
{
InitializePrintStruct ();
if (!pPrintDlgStruct)
return;
}
if (!DialogBoxParam (hInst, "IDD_PRINT", hwndMain, PrintProc, (LPARAM)lpDIB))
return;
SetCursor (LoadCursor (NULL, IDC_WAIT));
pDevNames = (LPDEVNAMES)GlobalLock (pPrintDlgStruct->hDevNames);
pDevMode = (LPDEVMODE)GlobalLock (pPrintDlgStruct->hDevMode);
pDevMode->dmCopies = uPrintCopies;
hDC = CreateDC ((LPCSTR)pDevNames + pDevNames->wDriverOffset, (LPCSTR)pDevNames + pDevNames->wDeviceOffset,
(LPCSTR)pDevNames + pDevNames->wOutputOffset, pDevMode);
if (bHalftoneImgLib)
{
lpDIBPrint = HalftoneDIB (lpDIB);
pBih = (LPBITMAPINFOHEADER) lpDIBPrint;
}
else
{
pBih = (LPBITMAPINFOHEADER) lpDIB;
}
iXMargin = GetDeviceCaps (hDC, HORZRES) / 20;
iYMargin = GetDeviceCaps (hDC, VERTRES) / 20;
if (bFillPage)
{
iWidth = GetDeviceCaps (hDC, HORZRES) - iXMargin * 2;
iHeight = GetDeviceCaps (hDC, VERTRES) - iYMargin * 2;
if (iWidth / pBih->biWidth > iHeight / pBih->biHeight)
iWidth = (int)pBih->biWidth * iHeight / (int)pBih->biHeight;
else
iHeight = (int)pBih->biHeight * iWidth / (int)pBih->biWidth;
}
else
{
iWidth = (int)pBih->biWidth;
iHeight = (int)pBih->biHeight;
/*
* ImgLib halftonning increases the image size 4 times. To make the
* output look the same size, size the output the same for GDI.
*/
if (!bHalftoneImgLib)
{
iWidth *= 4;
iHeight *= 4;
}
}
pBmi = (LPBITMAPINFO)pBih;
GetWindowText (hwndMain, szTitle, sizeof (szTitle));
DocInfo.cbSize = sizeof (DocInfo);
DocInfo.lpszDocName = szTitle;
DocInfo.lpszOutput = NULL;
StartDoc (hDC, &DocInfo);
StartPage (hDC);
StretchDIBits (hDC, iXMargin, iYMargin, iWidth, iHeight, 0, 0, (int)pBih->biWidth,
(int)pBih->biHeight, (HPSTR)&pBmi->bmiColors[pBih->biClrUsed], pBmi,
DIB_RGB_COLORS, SRCCOPY);
EndPage (hDC);
EndDoc (hDC);
DeleteDC (hDC);
if (lpDIBPrint)
DIBFree (lpDIBPrint);
GlobalUnlock (pPrintDlgStruct->hDevNames);
GlobalUnlock (pPrintDlgStruct->hDevMode);
SetCursor (LoadCursor (NULL, IDC_ARROW));
}
/*************************************************************************
Function: InitializePrintStruct ()
Purpose: Initialize the printing structure with default printer information.
Returns: none
*************************************************************************/
static void InitializePrintStruct (void)
{
if (pPrintDlgStruct)
freemem (pPrintDlgStruct);
pPrintDlgStruct = (LPPRINTDLG)allocmem (sizeof (PRINTDLG));
if (pPrintDlgStruct)
{
#ifdef WIN32
memset (pPrintDlgStruct, 0, sizeof (PRINTDLG));
#else
_fmemset (pPrintDlgStruct, 0, sizeof (PRINTDLG));
#endif
pPrintDlgStruct->lStructSize = sizeof (PRINTDLG);
pPrintDlgStruct->hwndOwner = hwndMain;
pPrintDlgStruct->Flags = PD_PRINTSETUP | PD_RETURNDEFAULT;
if (PrintDlg (pPrintDlgStruct) == FALSE)
{
freemem (pPrintDlgStruct);
pPrintDlgStruct = NULL;
MessageBox (hwndMain, "Error getting the default printer information", WINDOW_NAME, MB_OK | MB_ICONSTOP);
return;
}
}
}
/*************************************************************************
Function: HandleMenuPopup ()
Purpose: Prepare a menu for display based on the current application state
Returns: none
*************************************************************************/
static void HandleMenuPopup (WPARAM wParam, LPARAM lParam)
{
HMENU hMenuParent, hMenuPopup;
UINT uIndex;
BOOL bSystemMenu;
HDC hDC;
LPBITMAPINFOHEADER pBmi;
bSystemMenu = HIWORD (lParam);
if (bSystemMenu)
return;
hMenuParent = GetMenu (hwndMain);
hMenuPopup = (HMENU)wParam;
uIndex = LOWORD (lParam);
if (hMenuPopup == GetSubMenu (hMenuParent, 0))
{
if (lpDIBDisplay)
{
EnableMenuItem (hMenuPopup, ID_FILE_SAVE, MF_BYCOMMAND | MF_ENABLED);
EnableMenuItem (hMenuPopup, ID_FILE_PRINT, MF_BYCOMMAND | MF_ENABLED);
}
else
{
EnableMenuItem (hMenuPopup, ID_FILE_SAVE, MF_BYCOMMAND | MF_GRAYED);
EnableMenuItem (hMenuPopup, ID_FILE_PRINT, MF_BYCOMMAND | MF_GRAYED);
}
}
else if (hMenuPopup == GetSubMenu (hMenuParent, 1))
{
if (lpDIB1 && lpDIB2)
EnableMenuItem (hMenuPopup, ID_EDIT_UNDO, MF_BYCOMMAND | MF_ENABLED);
else
EnableMenuItem (hMenuPopup, ID_EDIT_UNDO, MF_BYCOMMAND | MF_GRAYED);
if (lpDIB1)
EnableMenuItem (hMenuPopup, ID_EDIT_COPY, MF_BYCOMMAND | MF_ENABLED);
else
EnableMenuItem (hMenuPopup, ID_EDIT_COPY, MF_BYCOMMAND | MF_GRAYED);
if (IsClipboardFormatAvailable (CF_BITMAP) || IsClipboardFormatAvailable (CF_DIB))
EnableMenuItem (hMenuPopup, ID_EDIT_PASTE, MF_BYCOMMAND | MF_ENABLED);
else
EnableMenuItem (hMenuPopup, ID_EDIT_PASTE, MF_BYCOMMAND | MF_GRAYED);
if (bDrawSelection)
EnableMenuItem (hMenuPopup, ID_EDIT_ZOOM, MF_BYCOMMAND | MF_ENABLED);
else
EnableMenuItem (hMenuPopup, ID_EDIT_ZOOM, MF_BYCOMMAND | MF_GRAYED);
}
else if (hMenuPopup == GetSubMenu (hMenuParent, 2))
{
if (lpDIB1)
{
pBmi = (LPBITMAPINFOHEADER) lpDIBDisplay;
/*
* Disallow controlling brightness of monochrome bitmaps
*/
if (pBmi->biPlanes * pBmi->biBitCount > 1)
EnableMenuItem (hMenuPopup, ID_PROCESS_BRIGHTNESS, MF_BYCOMMAND | MF_ENABLED);
else
EnableMenuItem (hMenuPopup, ID_PROCESS_BRIGHTNESS, MF_BYCOMMAND | MF_GRAYED);
EnableMenuItem (hMenuPopup, ID_PROCESS_SMOOTH, MF_BYCOMMAND | MF_ENABLED);
EnableMenuItem (hMenuPopup, ID_PROCESS_HALFTONE, MF_BYCOMMAND | MF_ENABLED);
EnableMenuItem (hMenuPopup, ID_PROCESS_GRAY, MF_BYCOMMAND | MF_ENABLED);
if (pBmi->biPlanes * pBmi->biBitCount <= 8)
EnableMenuItem (hMenuPopup, ID_PROCESS_EXPAND, MF_BYCOMMAND | MF_ENABLED);
else
EnableMenuItem (hMenuPopup, ID_PROCESS_EXPAND, MF_BYCOMMAND | MF_GRAYED);
EnableMenuItem (hMenuPopup, MENU_POSITION_ROTATE, MF_BYPOSITION | MF_ENABLED);
EnableMenuItem (hMenuPopup, MENU_POSITION_MIRROR, MF_BYPOSITION | MF_ENABLED);
}
else
{
EnableMenuItem (hMenuPopup, ID_PROCESS_BRIGHTNESS, MF_BYCOMMAND | MF_GRAYED);
EnableMenuItem (hMenuPopup, ID_PROCESS_SMOOTH, MF_BYCOMMAND | MF_GRAYED);
EnableMenuItem (hMenuPopup, ID_PROCESS_HALFTONE, MF_BYCOMMAND | MF_GRAYED);
EnableMenuItem (hMenuPopup, ID_PROCESS_GRAY, MF_BYCOMMAND | MF_GRAYED);
EnableMenuItem (hMenuPopup, ID_PROCESS_EXPAND, MF_BYCOMMAND | MF_GRAYED);
EnableMenuItem (hMenuPopup, MENU_POSITION_ROTATE, MF_BYPOSITION | MF_GRAYED);
EnableMenuItem (hMenuPopup, MENU_POSITION_MIRROR, MF_BYPOSITION | MF_GRAYED);
}
}
else if (hMenuPopup == GetSubMenu (hMenuParent, 3))
{
hDC = GetDC (NULL);
if (GetDeviceCaps (hDC, BITSPIXEL) > 8)
EnableMenuItem (hMenuPopup, MENU_POSITION_TC_OPT, MF_BYPOSITION | MF_GRAYED);
else
EnableMenuItem (hMenuPopup, MENU_POSITION_TC_OPT, MF_BYPOSITION | MF_ENABLED);
ReleaseDC (NULL, hDC);
}
}
/*************************************************************************
Function: HandleLButtonDown ()
Purpose: Process the WM_LBUTTONDOWN message
Returns: none
*************************************************************************/
static void HandleLButtonDown (WPARAM wParam, LPARAM lParam)
{
SetCapture (hwndMain);
if (!bPasting)
{
if (bDrawSelection)
EraseSelectionBox ();
else
bDrawSelection = TRUE;
ptAnchor.x = rcSelection.left = rcSelection.right = LOWORD (lParam);
ptAnchor.y = rcSelection.top = rcSelection.bottom = HIWORD (lParam);
DrawSelectionBox ();
}
}
/*************************************************************************
Function: HandleLButtonUp ()
Purpose: Process the WM_LBUTTONUP message
Returns: none
*************************************************************************/
static void HandleLButtonUp (WPARAM wParam, LPARAM lParam)
{
HANDLE hDIB;
LPBITMAPINFOHEADER pBih;
HBITMAP hBitmap;
HPALETTE hPalTemp;
LPVOID lpDIBNew, lpDIBTemp;
if (bPasting)
{
if (OpenClipboard (hwndMain))
{
SetCursor (LoadCursor (NULL, IDC_WAIT));
if (IsClipboardFormatAvailable (CF_DIB))
{
hDIB = GetClipboardData (CF_DIB);
pBih = (LPBITMAPINFOHEADER)GlobalLock (hDIB);
lpDIBNew = MergeDIB (lpDIB1, pBih, rcSelection.left, rcSelection.top);
GlobalUnlock (hDIB);
}
else if (IsClipboardFormatAvailable (CF_BITMAP))
{
hBitmap = GetClipboardData (CF_BITMAP);
hPalTemp = GetClipboardData (CF_PALETTE);
lpDIBTemp = DDBToDIB (hBitmap, hPalTemp);
if (lpDIBTemp)
{
lpDIBNew = MergeDIB (lpDIB1, lpDIBTemp, rcSelection.left, rcSelection.top);
DIBFree (lpDIBTemp);
}
}
else
{
CloseClipboard ();
return;
}
CloseClipboard ();
EraseSelectionBox ();
bDrawSelection = FALSE;
ProcessNewDIB (lpDIBNew);
SetCursor (LoadCursor (NULL, IDC_ARROW));
}
bPasting = FALSE;
}
else
{
if (rcSelection.right - rcSelection.left < 5 || rcSelection.bottom - rcSelection.top < 5)
{
EraseSelectionBox ();
bDrawSelection = FALSE;
}
}
ReleaseCapture ();
}
/*************************************************************************
Function: HandleRButtonDown ()
Purpose: Process the WM_RBUTTONDOWN message
Returns: none
*************************************************************************/
static void HandleRButtonDown (WPARAM wParam, LPARAM lParam)
{
if (GetCapture () == hwndMain)
{
EraseSelectionBox ();
bDrawSelection = FALSE;
bPasting = FALSE;
ReleaseCapture ();
}
}
/*************************************************************************
Function: HandleMouseMove ()
Purpose: Process the WM_MOUSEMOVE message
Returns: none
*************************************************************************/
static void HandleMouseMove (WPARAM wParam, LPARAM lParam)
{
LONG lX, lY, ldx, ldy;
if (GetCapture () == hwndMain)
{
EraseSelectionBox ();
lX = LOWORD (lParam);
lY = HIWORD (lParam);
if (lX < 0)
lX = 0;
if (lY < 0)
lY = 0;
if (bPasting)
{
ldx = lX - rcSelection.left;
ldy = lY - rcSelection.top;
OffsetRect (&rcSelection, (int)ldx, (int)ldy);
}
else
{
if (lX > ptAnchor.x)
{
rcSelection.right = (int)lX;
rcSelection.left = ptAnchor.x;
}
else
{
rcSelection.left = (int)lX;
rcSelection.right = ptAnchor.x;
}
if (lY > ptAnchor.y)
{
rcSelection.bottom = (int)lY;
rcSelection.top = ptAnchor.y;
}
else
{
rcSelection.top = (int)lY;
rcSelection.bottom = ptAnchor.y;
}
}
DrawSelectionBox ();
}
}
/*************************************************************************
Function: HandleCharacter ()
Purpose: Process the WM_CHAR message
Returns: none
*************************************************************************/
static void HandleCharacter (WPARAM wParam, LPARAM lParam)
{
if (GetCapture () == hwndMain && wParam == VK_ESCAPE)
{
EraseSelectionBox ();
bDrawSelection = FALSE;
bPasting = FALSE;
ReleaseCapture ();
}
}
/*************************************************************************
Function: HandlePasting ()
Purpose: Process the clipdoard paste
Returns: none
*************************************************************************/
static void HandlePasting (WPARAM wParam, LPARAM lParam)
{
HANDLE hDIB;
LPBITMAPINFOHEADER pBih;
long lWidth, lHeight;
HBITMAP hBitmap;
BITMAP bm;
POINT ptCursor;
LPVOID lpDIBNew;
HPALETTE hPalTemp;
if (OpenClipboard (hwndMain))
{
if (lpDIB1)
{
if (IsClipboardFormatAvailable (CF_DIB))
{
hDIB = GetClipboardData (CF_DIB);
pBih = (LPBITMAPINFOHEADER)GlobalLock (hDIB);
lWidth = pBih->biWidth;
lHeight = pBih->biHeight;
GlobalUnlock (hDIB);
}
else if (IsClipboardFormatAvailable (CF_BITMAP))
{
hBitmap = GetClipboardData (CF_BITMAP);
GetObject (hBitmap, sizeof (bm), &bm);
lWidth = bm.bmWidth;
lHeight = bm.bmHeight;
}
else
{
CloseClipboard ();
return;
}
GetCursorPos (&ptCursor);
ScreenToClient (hwndMain, &ptCursor);
rcSelection.left = ptCursor.x;
rcSelection.top = ptCursor.y;
rcSelection.right = ptCursor.x + (int)lWidth;
rcSelection.bottom = ptCursor.y + (int)lHeight;
bDrawSelection = TRUE;
bPasting = TRUE;
DrawSelectionBox ();
SetCapture (hwndMain);
}
else
{
if (IsClipboardFormatAvailable (CF_DIB))
{
hDIB = GetClipboardData (CF_DIB);
pBih = (LPBITMAPINFOHEADER)GlobalLock (hDIB);
lpDIBNew = CopyDIB (pBih);
GlobalUnlock (hDIB);
}
else if (IsClipboardFormatAvailable (CF_BITMAP))
{
hBitmap = GetClipboardData (CF_BITMAP);
hPalTemp = GetClipboardData (CF_PALETTE);
lpDIBNew = DDBToDIB (hBitmap, hPalTemp);
}
else
{
CloseClipboard ();
return;
}
ProcessNewDIB (lpDIBNew);
}
CloseClipboard ();
}
}
/*************************************************************************
Function: HandleCopying ()
Purpose: Process the clipdoard copy
Returns: none
*************************************************************************/
static void HandleCopying (WPARAM wParam, LPARAM lParam)
{
LPVOID lpDIBTemp, lpDIB;
DWORD dwSize;
HANDLE hDIB;
if (lpDIB1)
{
if (OpenClipboard (hwndMain))
{
if (bDrawSelection)
{
EraseSelectionBox ();
bDrawSelection = FALSE;
lpDIBTemp = ClipDIB (lpDIB1, rcSelection.left, rcSelection.top, rcSelection.right - rcSelection.left + 1, rcSelection.bottom - rcSelection.top + 1);
}
else
lpDIBTemp = lpDIB1;
if (lpDIBTemp)
{
dwSize = GetDIBSize (lpDIBTemp);
hDIB = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, dwSize);
lpDIB = GlobalLock (hDIB);
if (lpDIB)
{
copymem (lpDIB, lpDIBTemp, dwSize);
GlobalUnlock (hDIB);
EmptyClipboard ();
SetClipboardData (CF_DIB, hDIB);
}
if (bDrawSelection)
DIBFree (lpDIBTemp);
}
CloseClipboard ();
}
}
}
/*************************************************************************
Function: HandleZoomin ()
Purpose: Process the zoomin procedure
Returns: none
*************************************************************************/
static void HandleZoomin (WPARAM wParam, LPARAM lParam)
{
LPVOID lpDIBTemp, lpDIBNew;
if (lpDIB1 && bDrawSelection)
{
SetCursor (LoadCursor (NULL, IDC_WAIT));
EraseSelectionBox ();
bDrawSelection = FALSE;
lpDIBTemp = ClipDIB (lpDIB1, rcSelection.left, rcSelection.top, rcSelection.right - rcSelection.left + 1, rcSelection.bottom - rcSelection.top + 1);
if (lpDIBTemp)
{
lpDIBNew = ZoomDIB (lpDIBTemp, 500, 500);
DIBFree (lpDIBTemp);
if (lpDIBNew)
ProcessNewDIB (lpDIBNew);
}
SetCursor (LoadCursor (NULL, IDC_ARROW));
}
}
/*************************************************************************
Function: DrawSelectionBox ()
Purpose: Draw the selection
Returns: none
*************************************************************************/
static void DrawSelectionBox (void)
{
HDC hDC;
UpdateWindow (hwndMain);
hDC = GetDC (hwndMain);
if (hDC)
{
SetROP2 (hDC, R2_XORPEN);
SelectObject (hDC, GetStockObject (WHITE_PEN));
SelectObject (hDC, GetStockObject (HOLLOW_BRUSH));
Rectangle (hDC, rcSelection.left, rcSelection.top, rcSelection.right, rcSelection.bottom);
ReleaseDC (hwndMain, hDC);
}
}
/*************************************************************************
Function: EraseSelectionBox ()
Purpose: Erase the selection
Returns: none
*************************************************************************/
static void EraseSelectionBox (void)
{
if (bDrawSelection)
DrawSelectionBox ();
}
/*************************************************************************
Function: ProcessNewDIB ()
Purpose: Set up to display a newly loaded/created DIB
Returns: none
*************************************************************************/
static void ProcessNewDIB (LPVOID lpDIBNew)
{
if (lpDIBNew && lpDIBNew != lpDIB1)
{
if (lpDIBDisplay && lpDIBDisplay != lpDIB1)
DIBFree (lpDIBDisplay);
if (lpDIB2)
DIBFree (lpDIB2);
lpDIB2 = lpDIB1;
lpDIB1 = lpDIBNew;
if (hPalette)
{
DeleteObject (hPalette);
hPalette = NULL;
}
lpDIBDisplay = CreateDisplayDIB (hwndMain, &lpDIB1, &hPalette);
if (lpDIBDisplay)
ResizeWindowToDIB (hwndMain, lpDIBDisplay);
}
}
/*************************************************************************
Function: HandlePaintingAndUpdates ()
Purpose: Process image painting and palette management
Returns: none
*************************************************************************/
static LRESULT HandlePaintingAndUpdates (UINT message, WPARAM wParam, LPARAM lParam)
{
RECT rcClient;
HPALETTE hPalOld;
HDC hDC;
int iCount, iXPos, iYPos, iYStart;
PAINTSTRUCT PaintStruct;
HPSTR hpBits;
LPBITMAPINFO pBitmapInfo;
switch (message)
{
case WM_QUERYNEWPALETTE:
/*
* If palette realization causes a palette change,
* we need to do a full redraw.
*/
if (hPalette && wParam != (UINT)hwndMain)
{
hDC = GetDC (hwndMain);
hPalOld = SelectPalette (hDC, hPalette, FALSE);
iCount = RealizePalette (hDC);
InvalidateRect (hwndMain, (LPRECT) (NULL), FALSE);
UpdateWindow (hwndMain);
SelectPalette (hDC, hPalOld, 0);
ReleaseDC (hwndMain, hDC);
return TRUE;
}
break;
case WM_PALETTECHANGED:
if (hPalette && wParam != (UINT)hwndMain)
InvalidateRect (hwndMain, (LPRECT) (NULL), FALSE);
break;
case WM_PAINT:
hDC = BeginPaint (hwndMain, &PaintStruct);
if (lpDIBDisplay)
{
if (hPalette)
{
hPalOld = SelectPalette (hDC, hPalette, FALSE);
RealizePalette (hDC);
}
GetClientRect (hwndMain, &rcClient);
iXPos = GetScrollPos (hwndMain, SB_HORZ);
iYPos = GetScrollPos (hwndMain, SB_VERT);
pBitmapInfo = (LPBITMAPINFO) lpDIBDisplay;
#ifdef USE_WING
if (hWinGInst && hbmpWinG)
{
fpWinGStretchBlt (hDC, 0, 0, rcClient.right, rcClient.bottom, hdcWinG, iXPos, iYPos,
rcClient.right, rcClient.bottom);
}
else
#endif
{
iYStart = (int)pBitmapInfo->bmiHeader.biHeight - rcClient.bottom - iYPos;
hpBits = (HPSTR)&pBitmapInfo->bmiColors[pBitmapInfo->bmiHeader.biClrUsed];
StretchDIBits (hDC, 0, 0, rcClient.right, rcClient.bottom, iXPos, iYStart,
rcClient.right, rcClient.bottom, hpBits, pBitmapInfo, DIB_RGB_COLORS, SRCCOPY);
}
if (hPalette)
SelectPalette (hDC, hPalOld, FALSE);
}
if (bDrawSelection)
DrawSelectionBox ();
EndPaint (hwndMain, &PaintStruct);
break;
}
return (0);
}
#ifdef USE_WING
/*************************************************************************
Function: InitializeWinG ()
Purpose: Initializes WinG
Returns: none
*************************************************************************/
static void InitializeWinG ()
{
fpWinGCreateDC = (WINGCREATEDC) GetProcAddress (hWinGInst, "WinGCreateDC");
fpWinGCreateBitmap = (WINGCREATEBITMAP) GetProcAddress (hWinGInst, "WinGCreateBitmap");
fpWinGStretchBlt = (WINGSTRETCHBLT) GetProcAddress (hWinGInst, "WinGStretchBlt");
hdcWinG = fpWinGCreateDC ();
}
/*************************************************************************
Function: UpdateWinGBitmap ()
Purpose: Updates WinG bitmap used to draw DIBs
Returns: none
*************************************************************************/
static void UpdateWinGBitmap (LPVOID lpDIB)
{
LPBITMAPINFO pBiDIB = (LPBITMAPINFO) lpDIB;
HPALETTE hpalTemp, hpalOld;
HPSTR hpBits;
if (hbmpWinG)
{
SelectObject (hdcWinG, hbmpWinGOld);
DeleteObject (hbmpWinG);
}
/*
* Create a new bitmap and put it in WinG DC for quick repaints. WinG
* deals with 8-bit-per-pixel bitmaps only.
*/
hbmpWinG = fpWinGCreateBitmap (hdcWinG, pBiDIB, NULL);
if (hbmpWinG)
{
hbmpWinGOld = SelectObject (hdcWinG, hbmpWinG);
hpalTemp = CreateDIBPalette (lpDIB);
hpalOld = SelectPalette (hdcWinG, hpalTemp, FALSE);
RealizePalette (hdcWinG);
hpBits = (HPSTR)&pBiDIB->bmiColors[pBiDIB->bmiHeader.biClrUsed];
StretchDIBits (hdcWinG, 0, 0, (int)pBiDIB->bmiHeader.biWidth, (int)pBiDIB->bmiHeader.biHeight, 0, 0,
(int)pBiDIB->bmiHeader.biWidth, (int)pBiDIB->bmiHeader.biHeight, hpBits, pBiDIB, DIB_RGB_COLORS, SRCCOPY);
SelectPalette (hdcWinG, hpalOld, FALSE);
DeleteObject (hpalTemp);
}
}
#endif