VIEWWP.C

/****************************************************************************/ 
/* */
/* Copyright (C) 1987-1996 Microsoft Corp. */
/* All Rights Reserved */
/* */
/****************************************************************************/
/****************************** Module Header *******************************
* Module Name: viewwp.c
*
* Contains routines that handle the View window.
*
* History:
*
* 07/17/91 - - Created.
*
****************************************************************************/

#include "imagedit.h"
#include "dialogs.h"

#include <windowsx.h>

/*
* Style of the view window. */
#define VIEWSTYLE (WS_POPUP | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU)


STATICFN VOID NEAR ViewChar(UINT uiChar);


static INT gViewBackMargin; // Margin of background within view window.



/****************************************************************************
* ViewCreate
*
* This function creates the View window.
*
* History:
*
****************************************************************************/

VOID ViewCreate(VOID)
{
INT x;
INT y;
INT cxDummy;
INT cyDummy;
RECT rc;
BOOL fMaximized;

gViewBackMargin = GetSystemMetrics(SM_CXVSCROLL) / 2;

/*
* Get the saved position of the Toolbox. Note that we throw away
* the size fields, because we will calculate the required size
* later based on the image size.
*/
if (!ReadWindowPos(szViewPos, &x, &y, &cxDummy, &cyDummy, &fMaximized)) {
/*
* The previous position of the View window couldn't be found.
* Position the window to the right side of the editor, just
* below the Toolbox.
*/
if (ghwndToolbox) {
GetWindowRect(ghwndToolbox, &rc);
x = rc.left;
y = rc.bottom + (2 * PALETTEMARGIN);
}
else {
/*
* Last resort. Position it in the upper left corner
* of the screen if the Toolbox cannot be found. This
* is unlikely because if the previous position of the
* View window could not be found, this implies that
* the editor has not been run before on this machine.
* If this is true, the toolbox will come up by default
* before this routine is called. But just in case...
*/
x = 2 * PALETTEMARGIN;
y = 2 * PALETTEMARGIN;
}
}

if (!(ghwndView = CreateWindow(szViewClass, NULL, VIEWSTYLE,
x, y, 0, 0, ghwndMain, NULL, ghInst, NULL)))
return;
}



/****************************************************************************
* ViewShow
*
* This function shows or hides the view window.
*
* History:
*
****************************************************************************/

VOID ViewShow(
BOOL fShow)
{
if (fShow) {
/*
* Only show it if there is an image to display!
*/
if (gpImageCur)
ShowWindow(ghwndView, SW_SHOWNA);
}
else {
ShowWindow(ghwndView, SW_HIDE);
}
}



/****************************************************************************
* ViewUpdate
*
* This function updates the view window. It should be called any time that
* the image changes (is drawn upon).
*
* History:
*
****************************************************************************/

VOID ViewUpdate(VOID)
{
InvalidateRect(ghwndView, NULL, TRUE);

/*
* Update the workspace window also, because it must always
* match the state of the View window.
*/
WorkUpdate();
}



/****************************************************************************
* ViewReset
*
* This function resets the view window, sizing it to fit a new
* image. It should be called any time that the current image
* is changed to another one.
*
* History:
*
****************************************************************************/

VOID ViewReset(VOID)
{
RECT rc;
RECT rcT;

GetWindowRect(ghwndView, &rc);

rcT.left = 0;
rcT.top = 0;
rcT.right = PALETTEMARGIN + gViewBackMargin +
gpImageCur->cx + gViewBackMargin + PALETTEMARGIN;
rcT.bottom = PALETTEMARGIN + gViewBackMargin +
gpImageCur->cy + gViewBackMargin + PALETTEMARGIN;
AdjustWindowRect(&rcT, VIEWSTYLE, FALSE);

rc.right = rc.left + (rcT.right - rcT.left);
rc.bottom = rc.top + (rcT.bottom - rcT.top);
FitRectToScreen(&rc);

SetWindowPos(ghwndView, NULL, rc.left, rc.top,
rc.right - rc.left, rc.bottom - rc.top,
SWP_NOACTIVATE | SWP_NOZORDER);

/*
* If the user wants it, show the View window now.
*/
if (gfShowView)
ViewShow(TRUE);

ViewUpdate();

/*
* Clear out the propbar size and position fields, because they
* probably show the wrong information now.
*/
PropBarClearPos();
PropBarClearSize();
}



/****************************************************************************
* ViewWndProc
*
* This is the window procedure for the view window.
*
* History:
*
****************************************************************************/

WINDOWPROC ViewWndProc(
HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
switch (msg) {
case WM_CREATE:
{
HMENU hmenu = GetSystemMenu(hwnd, FALSE);

RemoveMenu(hmenu, 7, MF_BYPOSITION); // Second separator.
RemoveMenu(hmenu, 5, MF_BYPOSITION); // First separator.

RemoveMenu(hmenu, SC_RESTORE, MF_BYCOMMAND);
RemoveMenu(hmenu, SC_SIZE, MF_BYCOMMAND);
RemoveMenu(hmenu, SC_MINIMIZE, MF_BYCOMMAND);
RemoveMenu(hmenu, SC_MAXIMIZE, MF_BYCOMMAND);
RemoveMenu(hmenu, SC_TASKLIST, MF_BYCOMMAND);
}

return 0;

case WM_PAINT:
{
HDC hdc;
PAINTSTRUCT ps;
HBRUSH hbrOld;
RECT rc;

hdc = BeginPaint(hwnd, &ps);

/*
* The view window should not be showing if there
* is not an image to view!
*/
if (gpImageCur) {
DrawMarginBorder(hwnd, hdc);

GetClientRect(hwnd, &rc);
hbrOld = SelectObject(hdc, ghbrScreen);
PatBlt(hdc, PALETTEMARGIN + 1, PALETTEMARGIN + 1,
rc.right - (PALETTEMARGIN * 2) - 2,
rc.bottom - (PALETTEMARGIN * 2) - 2,
PATCOPY);
SelectObject(hdc, hbrOld);

BitBlt(hdc, PALETTEMARGIN + gViewBackMargin,
PALETTEMARGIN + gViewBackMargin,
gcxImage, gcyImage, ghdcImage, 0, 0, SRCCOPY);
}

EndPaint(hwnd, &ps);
}

break;

case WM_ACTIVATE:
if (GET_WM_ACTIVATE_STATE(wParam, lParam))
gidCurrentDlg = DID_VIEW;

break;

case WM_LBUTTONDOWN:
SetScreenColor(gargbCurrent[giColorLeft]);
break;

case WM_CHAR:
ViewChar(wParam);
break;

case WM_CLOSE:
/*
* The user closed the view window from the system menu.
* Hide the window (we don't actually destroy it so
* that it will appear in the same spot when they show
* it again).
*/
ViewShow(FALSE);
gfShowView = FALSE;
break;

case WM_DESTROY:
{
RECT rc;

/*
* Save the position of the toolbox.
*/
GetWindowRect(hwnd, &rc);
WriteWindowPos(&rc, FALSE, szViewPos);

/*
* Null out the global window handle for the view window
* for safety's sake.
*/
ghwndView = NULL;
}

break;

default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}

return 0;
}



/************************************************************************
* ViewChar
*
* Handles WM_CHAR messages for the view window. Currently this just
* includes the '+' and '-' keys, which are used to cycle through all
* the possible screen colors.
*
* Arguments:
*
* History:
*
************************************************************************/

STATICFN VOID NEAR ViewChar(
UINT uiChar)
{
INT i;
INT iNext;

switch (uiChar) {
/*
* Advance to the next screen color.
*/
case '+':
iNext = 0;
for (i = 0; i < 16; i++) {
if (grgbScreen == gargbDefaultColor[i]) {
iNext = i + 1;
break;
}
}

if (iNext >= 16)
iNext = 0;

SetScreenColor(gargbDefaultColor[iNext]);

break;

/*
* Back up to the prior screen color.
*/
case '-':
iNext = 16 - 1;
for (i = 0; i < 16; i++) {
if (grgbScreen == gargbDefaultColor[i]) {
iNext = i - 1;
break;
}
}

if (iNext < 0)
iNext = 16 - 1;

SetScreenColor(gargbDefaultColor[iNext]);

break;
}
}



/****************************************************************************
* ViewSetPixel
*
* This function colors a pixel in the View window directly. It is
* provided as an optimization when drawing a point. The ghdcImage
* bitmap must be updated as well or the image on the screen will
* get out of synch with it.
*
* History:
*
****************************************************************************/

VOID ViewSetPixel(
INT x,
INT y,
INT nBrushSize)
{
HDC hDC;
HBRUSH hbrOld;
INT Size;
INT SizeX;
INT SizeY;

hDC = GetDC(ghwndView);
hbrOld = SelectObject(hDC, ghbrDrawSolid);
SizeX = x - nBrushSize / 2;
SizeY = y - nBrushSize / 2;
PatBlt(hDC, PALETTEMARGIN + gViewBackMargin + (SizeX >= 0 ? SizeX : 0),
PALETTEMARGIN + gViewBackMargin + (SizeY >= 0 ? SizeY : 0),
((Size = gcxImage - SizeX) >= nBrushSize ?
nBrushSize : Size),
((Size = gcyImage - SizeY) >= nBrushSize ?
nBrushSize : Size), PATCOPY);
SelectObject(hDC, hbrOld);
ReleaseDC(ghwndView, hDC);
}



/****************************************************************************
* DrawMarginBorder
*
*
* History:
*
****************************************************************************/

VOID DrawMarginBorder(
HWND hwnd,
HDC hdc)
{
HBRUSH hbrOld;
HPEN hpenOld;
RECT rc;

GetClientRect(hwnd, &rc);
hpenOld = SelectObject(hdc, GetStockObject(BLACK_PEN));
hbrOld = SelectObject(hdc, GetStockObject(NULL_BRUSH));
Rectangle(hdc, PALETTEMARGIN, PALETTEMARGIN,
rc.right - PALETTEMARGIN,
rc.bottom - PALETTEMARGIN);
SelectObject(hdc, hpenOld);
SelectObject(hdc, hbrOld);
}



/****************************************************************************
* DrawSunkenRect
*
*
* History:
*
****************************************************************************/

VOID DrawSunkenRect(
PRECT prc,
HDC hdc)
{
HPEN hpenOld;

hpenOld = SelectObject(hdc, hpenDarkGray);
MoveToEx(hdc, prc->left, prc->top, NULL);
LineTo(hdc, prc->right - 1, prc->top);
MoveToEx(hdc, prc->left, prc->top, NULL);
LineTo(hdc, prc->left, prc->bottom - 1);

SelectObject(hdc, GetStockObject(WHITE_PEN));
MoveToEx(hdc, prc->left + 1, prc->bottom - 1, NULL);
LineTo(hdc, prc->right, prc->bottom - 1);
MoveToEx(hdc, prc->right - 1, prc->top + 1, NULL);
LineTo(hdc, prc->right - 1, prc->bottom - 1);

SelectObject(hdc, hpenOld);
}