/****************************************************************************/
/* */
/* 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);
}