|
|
/* pane.c - This file contains the multi-pane handling routines.
* * Copyright (c) 1991-, Microsoft Corporation. * All rights reserved. */
#include "packager.h"
#include <shellapi.h>
#include "dialogs.h"
//#define OLESVR_SUPPORT /* enable support for OLE server files */
#define DRAG_EMBED 2 // Ctrl + Drag
#define DRAG_LINK 6 // Ctrl + Shift + Drag
static HBRUSH hbrBlack; // Black brush
static HCURSOR hcurSplit; static HWND hwndDesc; static HWND hwndInsertIcon = NULL; static HWND hwndView = NULL; static INT cxBorder; // WS_BORDER border width
static INT cyBorder; static INT cxFudge = 0; // Fudge factors for good appearance
static INT cyFudge = 0; static INT cxMinWidth; static INT cxView; static INT cxSplit; // Splitter bar width
static INT cxPict; static INT cxDesc; static INT cxInsertIcon; static INT cxMin[CCHILDREN]; static INT cyHeight; static INT xSplit = 0; static CHAR szButton[] = "button"; static CHAR szStatic[] = "static"; static CHAR szPaneClass[] = "PaneClass"; static CHAR szSubtitleClass[] = "SubTitleClass"; static CHAR szDescription[CBMESSAGEMAX]; static CHAR szView[CBMESSAGEMAX]; static CHAR szPicture[CBMESSAGEMAX]; static CHAR szInsertIcon[CBMESSAGEMAX]; static CHAR szDropFile[CBPATHMAX]; static BOOL fHScrollEnable = FALSE; static BOOL fVScrollEnable = FALSE;
static BOOL MakeWindows(VOID); static INT GetTextLen(HDC hdc, LPSTR lpstr); static VOID RecalibrateScroll(INT iPane, DWORD lParam); static VOID Undo(INT iPane); static VOID CalcWindows(BOOL fFirst); static INT Constrain(INT x, INT right); static VOID CopyOther(VOID);
/* InitPaneClasses() - Do application "global" initialization.
* * This function registers the window classes used by the application. * Returns: TRUE if successful. */ BOOL InitPaneClasses( VOID ) { WNDCLASS wc;
wc.style = 0; wc.lpfnWndProc = SubtitleWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = ghInst; wc.hIcon = LoadIcon(ghInst, MAKEINTRESOURCE(ID_APPLICATION)); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); wc.lpszMenuName = MAKEINTRESOURCE(ID_APPLICATION); wc.lpszClassName = szSubtitleClass;
if (!RegisterClass(&wc)) return FALSE;
wc.style = CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW; wc.lpfnWndProc = PaneWndProc; wc.cbClsExtra = 0; // Reserve space for the item specific data handle
wc.cbWndExtra = sizeof(LPVOID); wc.hInstance = ghInst; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); wc.lpszMenuName = NULL; wc.lpszClassName = szPaneClass;
if (!RegisterClass(&wc)) return FALSE;
return TRUE; }
/* InitPanes() - Handles the instance-specific initialization.
* * This function creates the main application window. * Returns: TRUE if successful. */ BOOL InitPanes( VOID ) { LOGFONT lf; CHARSETINFO csinfo; LCID lcid = GetThreadLocale(); DWORD dwCp = GetACP();
hbrBlack = GetStockObject(BLACK_BRUSH); hcurSplit = LoadCursor(ghInst, MAKEINTRESOURCE(SPLIT)); gcxIcon = GetSystemMetrics(SM_CXICON); gcyIcon = GetSystemMetrics(SM_CYICON);
SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, FALSE); SystemParametersInfo(SPI_ICONHORIZONTALSPACING, 0, &gcxArrange, FALSE); SystemParametersInfo(SPI_ICONVERTICALSPACING, 0, &gcyArrange, FALSE);
// ANSI app needs to make sure it has the right charset for text rendering
if (TranslateCharsetInfo(&dwCp, &csinfo, TCI_SRCCODEPAGE)) lf.lfCharSet = (BYTE) csinfo.ciCharset;
// Lock down font size to 8 point size since we won't adjust window size
lf.lfHeight = -MulDiv(8, giYppli, 72); lf.lfWidth = 0;
ghfontTitle = CreateFontIndirect(&lf); if (PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_CHINESE || PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_JAPANESE) lf.lfWeight = FW_NORMAL; else lf.lfWeight = FW_BOLD; ghfontChild = CreateFontIndirect(&lf);
if (!(ghfontTitle || ghfontChild)) { if (ghfontTitle) DeleteObject(ghfontTitle);
return FALSE; }
LoadString(ghInst, IDS_CONTENT, gszCaption[CONTENT], CBMESSAGEMAX); LoadString(ghInst, IDS_VIEW, szView, CBMESSAGEMAX); LoadString(ghInst, IDS_DESCRIPTION, szDescription, CBMESSAGEMAX); LoadString(ghInst, IDS_PICTURE, szPicture, CBMESSAGEMAX); LoadString(ghInst, IDS_APPEARANCE, gszCaption[APPEARANCE], CBMESSAGEMAX); LoadString(ghInst, IDS_INSERTICON, szInsertIcon, CBMESSAGEMAX);
// Create the window panes
if (!MakeWindows()) return FALSE;
CalcWindows(TRUE);
// Give the focus to the content pane
PostMessage(ghwndPane[CONTENT], WM_LBUTTONDOWN, 0, 0L);
return TRUE; }
/* EndPaneInstance() - Instance-specific termination code.
*/ VOID EndPanes( VOID ) { if (ghfontTitle) DeleteObject(ghfontTitle);
if (ghfontChild) DeleteObject(ghfontChild); }
/* MakeWindows() - Make the window panes.
*/ static BOOL MakeWindows( VOID ) { if (ghwndBar[CONTENT] = CreateWindow(szSubtitleClass, gszCaption[CONTENT], WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, ghwndFrame, NULL, ghInst, NULL)) {
hwndView = CreateWindow(szStatic, szView, WS_CHILD | WS_VISIBLE | SS_LEFT | SS_CENTERIMAGE, 0, 0, 0, 0, ghwndBar[CONTENT], NULL, ghInst, NULL);
hwndDesc = CreateWindow(szButton, szDescription, WS_CHILD | BS_AUTORADIOBUTTON | WS_VISIBLE | WS_GROUP, 0, 0, 0, 0, ghwndBar[CONTENT], (HMENU)IDM_DESC, ghInst, NULL);
ghwndPict = CreateWindow(szButton, szPicture, WS_CHILD | BS_AUTORADIOBUTTON | WS_VISIBLE, 0, 0, 0, 0, ghwndBar[CONTENT], (HMENU)IDM_PICT, ghInst, NULL);
if (hwndView && hwndDesc && ghwndPict) { // Use the appropriate dialog font
SendMessage(ghwndBar[CONTENT], WM_SETFONT, (WPARAM)ghfontChild, TRUE); SendMessage(hwndView, WM_SETFONT, (WPARAM)ghfontChild, TRUE); SendMessage(hwndDesc, WM_SETFONT, (WPARAM)ghfontChild, TRUE); SendMessage(ghwndPict, WM_SETFONT, (WPARAM)ghfontChild, TRUE); CheckRadioButton(ghwndBar[CONTENT], IDM_PICT, IDM_DESC, IDM_DESC); EnableWindow(ghwndPict, FALSE); } else { goto Error; } } else { goto Error; }
if (ghwndBar[APPEARANCE] = CreateWindow(szSubtitleClass, gszCaption[APPEARANCE], WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, ghwndFrame, NULL, ghInst, NULL)) { hwndInsertIcon = CreateWindow(szButton, szInsertIcon, WS_CHILD | BS_PUSHBUTTON | WS_VISIBLE, 0, 0, 0, 0, ghwndBar[APPEARANCE], (HMENU)IDM_INSERTICON, ghInst, NULL);
if (hwndInsertIcon) { SendMessage(ghwndBar[APPEARANCE], WM_SETFONT, (WPARAM)ghfontChild, TRUE); SendMessage(hwndInsertIcon, WM_SETFONT, (WPARAM)ghfontChild, TRUE); } else { goto Error; } } else { goto Error; }
ghwndPane[APPEARANCE] = CreateWindowEx(WS_EX_CLIENTEDGE, szPaneClass, NULL, WS_BORDER | WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL, 0, 0, 0, 0, ghwndFrame, NULL, ghInst, NULL);
ghwndPane[CONTENT] = CreateWindowEx(WS_EX_CLIENTEDGE, szPaneClass, NULL, WS_BORDER | WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL, 0, 0, 0, 0, ghwndFrame, NULL, ghInst, NULL);
if (!ghwndPane[APPEARANCE] || !ghwndPane[CONTENT]) goto Error;
EnableScrollBar(ghwndPane[APPEARANCE], SB_HORZ, ESB_DISABLE_BOTH); EnableScrollBar(ghwndPane[APPEARANCE], SB_VERT, ESB_DISABLE_BOTH); EnableScrollBar(ghwndPane[CONTENT], SB_HORZ, ESB_DISABLE_BOTH); EnableScrollBar(ghwndPane[CONTENT], SB_VERT, ESB_DISABLE_BOTH);
DragAcceptFiles(ghwndPane[CONTENT], TRUE);
return TRUE;
Error: if (ghwndBar[CONTENT]) { if (hwndView) DestroyWindow(hwndView);
if (hwndDesc) DestroyWindow(hwndDesc);
if (ghwndPict) DestroyWindow(ghwndPict);
DestroyWindow(ghwndBar[CONTENT]); }
if (ghwndBar[APPEARANCE]) { if (hwndInsertIcon) DestroyWindow(hwndInsertIcon);
DestroyWindow(ghwndBar[APPEARANCE]); }
if (ghwndPane[APPEARANCE]) DestroyWindow(ghwndPane[APPEARANCE]);
if (ghwndPane[CONTENT]) DestroyWindow(ghwndPane[CONTENT]);
return FALSE; }
/* SubtitleWndProc() - "Appearance" and "Content" bar window procedure.
*/ LRESULT CALLBACK SubtitleWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) { PAINTSTRUCT ps; RECT rcCaption; INT iPane;
iPane = (hWnd == ghwndBar[CONTENT]);
switch (msg) { case WM_COMMAND: switch (LOWORD(wParam)) { case IDM_INSERTICON: Raise(APPEARANCE); DeletePane(APPEARANCE, FALSE);
if (gptyUndo[APPEARANCE] != ICON) glpobj[APPEARANCE] = IconCreateFromFile(""); else glpobj[APPEARANCE] = IconClone(glpobjUndo[APPEARANCE]);
if (glpobj[APPEARANCE]) gpty[APPEARANCE] = ICON;
if (glpobj[APPEARANCE] && IconDialog(glpobj[APPEARANCE])) { InvalidateRect(ghwndPane[APPEARANCE], NULL, TRUE); Dirty(); } else { IconDelete(glpobj[APPEARANCE]); gpty[APPEARANCE] = NOTHING; glpobj[APPEARANCE] = NULL; SendMessage(ghwndPane[APPEARANCE], WM_COMMAND, IDM_UNDO, 0); }
break;
case IDM_DESC: if (!IsDlgButtonChecked(ghwndBar[CONTENT], IDM_DESC)) CheckRadioButton(ghwndBar[CONTENT], IDM_PICT, IDM_DESC, IDM_DESC);
if (fHScrollEnable) EnableScrollBar(ghwndPane[iPane], SB_HORZ, ESB_DISABLE_BOTH);
if (fVScrollEnable) EnableScrollBar(ghwndPane[iPane], SB_VERT, ESB_DISABLE_BOTH);
InvalidateRect(ghwndPane[CONTENT], NULL, TRUE);
goto defProcess;
case IDM_PICT: if (!IsDlgButtonChecked(ghwndBar[CONTENT], IDM_PICT) && IsWindowEnabled(GetDlgItem(ghwndBar[CONTENT], IDM_PICT))) CheckRadioButton(ghwndBar[CONTENT], IDM_PICT, IDM_DESC, IDM_PICT);
if (fHScrollEnable) EnableScrollBar(ghwndPane[iPane], SB_HORZ, ESB_ENABLE_BOTH);
if (fVScrollEnable) EnableScrollBar(ghwndPane[iPane], SB_VERT, ESB_ENABLE_BOTH);
InvalidateRect(ghwndPane[CONTENT], NULL, TRUE); // Fall through
default: defProcess: if (GetTopWindow(ghwndFrame) != ghwndPane[iPane]) { if (gbDBCS) { /* 4-Oct-93 #2701 v-katsuy */ //win31#1203: 12/26/92:fixing Focus Line Scroll
//delete Focus Rect on another pane
InvalidateRect(ghwndPane[APPEARANCE], NULL, TRUE); } BringWindowToTop(ghwndPane[iPane]); InvalidateRect(ghwndBar[APPEARANCE], NULL, TRUE); InvalidateRect(ghwndBar[CONTENT], NULL, TRUE); if (LOWORD(wParam) == IDM_PICT || LOWORD(wParam) == IDM_DESC) UpdateWindow(ghwndPane[CONTENT]); } }
break;
case WM_LBUTTONDOWN: if (GetTopWindow(ghwndFrame) != ghwndPane[iPane]) SendMessage(ghwndPane[iPane], WM_LBUTTONDOWN, 0, 0);
break;
case WM_PAINT: { HFONT hfontOld;
GetClientRect(hWnd, &rcCaption); BeginPaint(hWnd, &ps);
if (GetTopWindow(ghwndFrame) == ghwndPane[iPane]) { SetTextColor(ps.hdc, GetSysColor(COLOR_HIGHLIGHTTEXT)); SetBkColor(ps.hdc, GetSysColor(COLOR_HIGHLIGHT)); } else { SetTextColor(ps.hdc, GetSysColor(COLOR_WINDOWTEXT)); SetBkColor(ps.hdc, GetSysColor(COLOR_WINDOW)); }
hfontOld = SelectObject(ps.hdc, ghfontChild); rcCaption.left += cxFudge; DrawText(ps.hdc, gszCaption[iPane], -1, &rcCaption, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_NOCLIP); SelectObject(ps.hdc, hfontOld);
EndPaint(hWnd, &ps); }
break;
case WM_SIZE: if (iPane == APPEARANCE) { if (hwndInsertIcon) { GetClientRect(hWnd, &rcCaption);
SetWindowPos(hwndInsertIcon, 0, rcCaption.right - cxInsertIcon, cyFudge, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
InvalidateRect(ghwndBar[APPEARANCE], NULL, TRUE); } } else { if (hwndView) { BOOL bChinese = PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale())) == LANG_CHINESE; GetClientRect(hWnd, &rcCaption); SetWindowPos(hwndView, 0, bChinese ? rcCaption.right - cxDesc - cxPict - cxView - 15 : rcCaption.right - cxDesc - cxPict - cxView, 0, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
SetWindowPos(hwndDesc, 0, rcCaption.right - cxDesc - cxPict, cyFudge, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
SetWindowPos(ghwndPict, 0, rcCaption.right - cxPict, cyFudge, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
InvalidateRect(ghwndBar[CONTENT], NULL, TRUE); } }
break;
default: return DefWindowProc(hWnd, msg, wParam, lParam); }
return 0L; }
static INT GetTextLen( HDC hdc, LPSTR lpstr ) { SIZE Size;
GetTextExtentPoint32(hdc, lpstr, lstrlen(lpstr), &Size);
return Size.cx + (cxFudge * 2); }
LRESULT CALLBACK PaneWndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) { BOOL fFocus; LPVOID lpobjTemp; PAINTSTRUCT ps; RECT rc; CHAR szFile[CBPATHMAX]; INT iOld; INT iPane; INT iPos; INT Max; INT Min; INT nBar;
iPane = (hwnd == ghwndPane[CONTENT]);
switch (msg) { case WM_HSCROLL: case WM_VSCROLL: // If not the content pane in picture mode, break
if (gpty[iPane] == PICTURE && iPane == CONTENT && !IsDlgButtonChecked(ghwndBar[CONTENT], IDM_PICT)) break;
// Can't scroll anything but cmd line and picture
if (gpty[iPane] != PICTURE && gpty[iPane] != CMDLINK) break;
nBar = (msg == WM_HSCROLL ? SB_HORZ : SB_VERT); iOld = iPos = GetScrollPos(hwnd, nBar);
switch (LOWORD(wParam)) { case SB_LINEUP: iPos--; break;
case SB_LINEDOWN: iPos++; break;
case SB_PAGEUP: case SB_PAGEDOWN: GetClientRect(hwnd, &rc); if (LOWORD(wParam) == SB_PAGEUP) iPos -= (rc.bottom - rc.top + 1); else iPos += (rc.bottom - rc.top + 1);
break;
case SB_THUMBPOSITION: iPos = (INT)HIWORD(wParam); break; }
// Make sure that iPos is in the range
GetScrollRange(hwnd, nBar, &Min, &Max);
if (iPos < Min) iPos = Min; if (iPos > Max) iPos = Max;
SetScrollPos(hwnd, nBar, iPos, TRUE);
if (msg == WM_HSCROLL) ScrollWindow(hwnd, iOld - iPos, 0, NULL, NULL); else ScrollWindow(hwnd, 0, iOld - iPos, NULL, NULL);
UpdateWindow(hwnd); break;
case WM_LBUTTONDOWN: if (GetTopWindow(ghwndFrame) != hwnd) { BringWindowToTop(hwnd); InvalidateRect(ghwndBar[APPEARANCE], NULL, TRUE); InvalidateRect(ghwndBar[CONTENT], NULL, TRUE); InvalidateRect(ghwndPane[APPEARANCE], NULL, TRUE); InvalidateRect(ghwndPane[CONTENT], NULL, TRUE); }
break;
case WM_PAINT: GetClientRect(hwnd, &rc); BeginPaint(hwnd, &ps); if (fFocus = (ghwndPane[iPane] == GetTopWindow(ghwndFrame))) { SetTextColor(ps.hdc, GetSysColor(COLOR_HIGHLIGHTTEXT)); SetBkColor(ps.hdc, GetSysColor(COLOR_HIGHLIGHT)); } else { SetTextColor(ps.hdc, GetSysColor(COLOR_WINDOWTEXT)); SetBkColor(ps.hdc, GetSysColor(COLOR_WINDOW)); }
switch (gpty[iPane]) { case CMDLINK: CmlDraw(glpobj[iPane], ps.hdc, &rc, GetScrollPos(hwnd, SB_HORZ), fFocus); break;
case PEMBED: EmbDraw(glpobj[iPane], ps.hdc, &rc, fFocus); break;
case ICON: IconDraw(glpobj[iPane], ps.hdc, &rc, fFocus, 0, 0); break;
case PICTURE: PicDraw(glpobj[iPane], ps.hdc, &rc, GetScrollPos(hwnd, SB_HORZ), GetScrollPos(hwnd, SB_VERT), hwnd == ghwndPane[APPEARANCE] || IsDlgButtonChecked(ghwndBar[CONTENT], IDM_PICT), fFocus); break;
default: FillRect(ps.hdc, &rc, ghbrBackground); break; }
EndPaint(hwnd, &ps); break;
case WM_FIXSCROLL: GetClientRect(hwnd, &rc); lParam = ((DWORD)rc.bottom << 16) | (DWORD)rc.right;
// Fall through
case WM_SIZE: if (gpty[iPane] == PICTURE || gpty[iPane] == CMDLINK) RecalibrateScroll(iPane, (DWORD)lParam);
break;
case WM_DESTROY: DeletePane(iPane, TRUE); break;
case WM_DROPFILES: { BYTE bKeyState = 0;
// Retrieve the file name
DragQueryFile((HANDLE)wParam, 0, szDropFile, CBPATHMAX);
DragFinish((HANDLE)wParam);
// We got dropped on, so bring ourselves to the top
BringWindowToTop(ghwndFrame); BringWindowToTop(hwnd);
// See what the user wants us to do
bKeyState = ((GetKeyState(VK_SHIFT) < 0) << 2) | ((GetKeyState(VK_CONTROL) < 0) << 1) | ((GetKeyState(VK_MENU) < 0));
switch (bKeyState) { case DRAG_LINK: PostMessage(hwnd, WM_COMMAND, IDM_LINKFILE, 0L); break;
case DRAG_EMBED: default: PostMessage(hwnd, WM_COMMAND, IDM_EMBEDFILE, 0L); break; }
break; }
case WM_LBUTTONDBLCLK: // Alt + Double Click = Properties
if (gpty[iPane] == PICTURE && GetKeyState(VK_MENU) < 0) { wParam = IDM_LINKS; } else { if (gpty[iPane] == PEMBED) { //
// If the server is a OLE server, we want to activate in
// OLE fashion. But from users perspective it should not
// look like an object. So for non-objects double-click
// implies show the server. We should try to do the same
// thing while editing ole server files.
//
wParam = IDD_EDIT; } else { wParam = IDD_PLAY; } }
msg = WM_COMMAND; lParam = 0;
// Fall through
case WM_COMMAND: switch (LOWORD(wParam)) { case IDM_COPY: case IDM_CUT: switch (gpty[iPane]) { case PICTURE: PicCopy(glpobj[iPane]);
default: if (iPane == APPEARANCE) CopyOther(); break; }
if (LOWORD(wParam) == IDM_COPY) break;
// Fall through to delete the selection
case IDM_CLEAR: DeletePane(iPane, FALSE); break;
case IDM_LINKS: { LONG objtype;
OleQueryType(((LPPICT)glpobj[iPane])->lpObject, &objtype); if (objtype == OT_LINK) DialogBoxAfterBlock(MAKEINTRESOURCE(DTPROP), ghwndPane[iPane], fnProperties);
break; } case IDM_LINKFILE: if(SUCCEEDED(StringCchCopy(szFile, ARRAYSIZE(szFile), szDropFile))) { wParam = IDM_PASTELINK; goto CreateFromFile; } break;
case IDM_EMBEDFILE: if(SUCCEEDED(StringCchCopy(szFile, ARRAYSIZE(szFile), szDropFile))) { wParam = IDM_PASTE; goto CreateFromFile; } break;
case IDM_PASTE: case IDM_PASTELINK: // Try to paste a file name from the File Manager
if (iPane == CONTENT) { HANDLE hdata; LPSTR lpstrFile;
if (IsClipboardFormatAvailable(gcfFileName)) { if (!OpenClipboard(ghwndFrame)) break;
if (!(hdata = GetClipboardData(gcfFileName)) || !(lpstrFile = GlobalLock(hdata))) { CloseClipboard(); break; }
StringCchCopy(szFile, ARRAYSIZE(szFile), lpstrFile); GlobalUnlock(hdata); CloseClipboard();
CreateFromFile:
#ifdef OLESVR_SUPPORT
if (IsOleServerDoc (szFile)) { lpobjTemp = PicFromFile((wParam == IDM_PASTE), szFile); if (!lpobjTemp) { ErrorMessage(E_GET_FROM_CLIPBOARD_FAILED); break; }
goto StuffNewObject; } else { #endif
DeletePane(CONTENT, FALSE); if (wParam == IDM_PASTE) { if (glpobj[CONTENT] = EmbCreate(szFile)) gpty[CONTENT] = PEMBED; } else { if (glpobj[CONTENT] = CmlCreateFromFilename(szFile, TRUE)) gpty[CONTENT] = CMDLINK; } #ifdef OLESVR_SUPPORT
} #endif
InvalidateRect(ghwndPane[CONTENT], NULL, TRUE); Dirty();
if (!gpty[APPEARANCE]) { if (glpobj[APPEARANCE] = IconCreateFromFile(szFile)) { gpty[APPEARANCE] = ICON; InvalidateRect(ghwndPane[APPEARANCE], NULL, TRUE); } }
break; } }
// Not a file name, try to paste an OLE object
if (!(lpobjTemp = PicPaste(LOWORD(wParam) == IDM_PASTE, gszCaption[iPane]))) { ErrorMessage(E_GET_FROM_CLIPBOARD_FAILED); break; } #ifdef OLESVR_SUPPORT
StuffNewObject:
#endif
DeletePane(iPane, FALSE); glpobj[iPane] = lpobjTemp; gpty[iPane] = PICTURE; SendMessage(ghwndPane[iPane], WM_FIXSCROLL, 0, 0L); InvalidateRect(ghwndPane[iPane], NULL, TRUE); Dirty();
if (iPane == CONTENT) { EnableWindow(ghwndPict, TRUE);
if (!gpty[APPEARANCE]) { if (glpobj[APPEARANCE] = IconCreateFromObject( ((LPPICT)glpobj[iPane])->lpObject)) { gpty[APPEARANCE] = ICON; InvalidateRect(ghwndPane[APPEARANCE], NULL, TRUE); } } }
Dirty(); break;
case IDD_EDIT: /* Edit the icon form */ case IDD_PLAY: switch (gpty[iPane]) { case CMDLINK: CmlActivate(glpobj[iPane]); break;
case PEMBED: EmbActivate(glpobj[iPane], LOWORD(wParam)); break;
case PICTURE: PicActivate(glpobj[iPane], LOWORD(wParam)); break;
default: break; }
break;
case IDD_UPDATE: /* Update the (link) object */ if (gpty[iPane] == PICTURE) PicUpdate(glpobj[iPane]);
break;
case IDD_FREEZE: /* Make the object static */ if (gpty[iPane] == PICTURE) PicFreeze(glpobj[iPane]);
break;
case IDD_CHANGE: if (gpty[iPane] == PICTURE) PicChangeLink(glpobj[iPane]);
break;
case IDM_UNDO: Undo(iPane); break;
case IDD_AUTO: /* Change the (link) update options */ case IDD_MANUAL: if (gpty[iPane] == PICTURE && !PicSetUpdateOptions(glpobj[iPane], LOWORD(wParam))) break;
case IDM_LINKDONE: /* The link update has completed */ PostMessage(ghwndError, WM_REDRAW, 0, 0L); break;
default: break; }
break;
default: return (DefWindowProc(hwnd, msg, wParam, lParam)); }
return 0; }
LRESULT CALLBACK SplitterFrame( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) { RECT rc;
switch (msg) { case WM_SIZE: if (wParam != SIZEICONIC && ghwndBar[APPEARANCE]) { GetClientRect(hWnd, &rc);
// Make sure the splitter bar is still valid
xSplit = Constrain(xSplit, rc.right); CalcWindows(FALSE);
// Invalidate the splitter bar, forcing a repaint
rc.left = xSplit - cxSplit / 2 - cxBorder; rc.right = xSplit + cxSplit / 2 + cxBorder; InvalidateRect(hWnd, &rc, TRUE); }
break;
case WM_PAINT: { PAINTSTRUCT ps; RECT rcBlack;
BeginPaint(hWnd, &ps); GetClientRect(hWnd, &rc);
SetRect(&rcBlack, xSplit - cxSplit / 2 - cxBorder, rc.top, xSplit + cxSplit / 2 + cxBorder, rc.top + cyHeight + cyBorder); FillRect(ps.hdc, &rcBlack, hbrBlack);
SetRect(&rcBlack, xSplit - cxSplit / 2 - cxBorder, rc.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1, xSplit + cxSplit / 2 + cxBorder, rc.bottom); FillRect(ps.hdc, &rcBlack, hbrBlack);
EndPaint(hWnd, &ps); break; }
case WM_GETMINMAXINFO: { LPPOINT rgpt = (LPPOINT)lParam;
rgpt[3].x = cxMinWidth; rgpt[3].y = cyHeight * 6; break; }
case WM_LBUTTONDOWN: { MSG msg1; INT x; INT y; INT dy; HDC hdc; HCURSOR hcurOld;
if (IsIconic(hWnd)) break;
x = LOWORD(lParam); GetClientRect(hWnd, &rc); y = 0; dy = rc.bottom;
// Constrain the splitter bar...
x = Constrain(x, rc.right); hdc = GetDC(hWnd);
// split bar loop
PatBlt(hdc, x - cxSplit / 2, y, cxSplit, dy, PATINVERT); SetCapture(hWnd); hcurOld = SetCursor(hcurSplit);
while (GetMessage(&msg1, NULL, 0, 0)) { if (msg1.message >= WM_MOUSEFIRST && msg1.message <= WM_MOUSELAST) { if (msg1.message == WM_LBUTTONUP || msg1.message == WM_LBUTTONDOWN) break;
if (msg1.message == WM_MOUSEMOVE) { ScreenToClient(hWnd, &msg1.pt); x = Constrain(x, rc.right);
// erase old
PatBlt(hdc, x - cxSplit / 2, y, cxSplit, dy, PATINVERT);
// put down new
x = Constrain(msg1.pt.x, rc.right); PatBlt(hdc, x - cxSplit / 2, y, cxSplit, dy, PATINVERT); } } else { DispatchMessage(&msg1); } }
SetCursor(hcurOld); ReleaseCapture();
// Constrain the splitter bar...
x = Constrain(x, rc.right);
// erase old
PatBlt(hdc, x - cxSplit / 2, y, cxSplit, dy, PATINVERT);
ReleaseDC(hWnd, hdc);
if (msg1.wParam != VK_ESCAPE) { xSplit = x; CalcWindows(FALSE); InvalidateRect(ghwndBar[APPEARANCE], NULL, TRUE); InvalidateRect(ghwndBar[CONTENT], NULL, TRUE); }
break; }
default: return FALSE; }
return TRUE; }
VOID DeletePane( INT iPane, BOOL fDeleteUndo ) { // Delete the last Undo object
if (glpobjUndo[iPane]) DeletePaneObject(glpobjUndo[iPane], gptyUndo[iPane]);
// If we don't wish to keep an undo, delete the object too!
if (fDeleteUndo) { DeletePaneObject(glpobj[iPane], gpty[iPane]); gptyUndo[iPane] = NOTHING; glpobjUndo[iPane] = NULL; } else { gptyUndo[iPane] = gpty[iPane]; glpobjUndo[iPane] = glpobj[iPane]; }
// Handle the buttons and such
if (gpty[iPane] == PICTURE || gpty[iPane] == CMDLINK) { CHAR szUndoName[CBMESSAGEMAX];
EnableScrollBar(ghwndPane[iPane], SB_HORZ, ESB_DISABLE_BOTH); EnableScrollBar(ghwndPane[iPane], SB_VERT, ESB_DISABLE_BOTH);
if (gpty[iPane] == PICTURE) { if (iPane == CONTENT) { CheckRadioButton(ghwndBar[CONTENT], IDM_PICT, IDM_DESC, IDM_DESC); EnableWindow(ghwndPict, FALSE); }
// If the Undo object isn't deleted already, rename it
if (!fDeleteUndo) { if(SUCCEEDED(StringCchPrintf(szUndoName, ARRAYSIZE(szUndoName), szUndo, gszCaption[iPane]))) { OleRename(((LPPICT)glpobjUndo[iPane])->lpObject, szUndoName); } } } }
glpobj[iPane] = NULL; gpty[iPane] = NOTHING;
if (IsWindow(ghwndPane[iPane])) InvalidateRect(ghwndPane[iPane], NULL, TRUE); }
static VOID RecalibrateScroll( INT iPane, DWORD lParam ) { INT cxDel; INT cyDel; BOOL bDesc = FALSE; LPPICT lppict = (LPPICT)glpobj[iPane];
// Compute the amount of scrolling possible
cxDel = lppict->rc.right - lppict->rc.left - (INT)(lParam & 0xffff); cyDel = lppict->rc.bottom - lppict->rc.top - (INT)(lParam >> 16);
// Normalize the scroll bar lengths
if (cxDel < 0) cxDel = 0;
if (cyDel < 0) cyDel = 0;
if (iPane == CONTENT) { bDesc = IsDlgButtonChecked(ghwndBar[iPane], IDM_DESC); fHScrollEnable = cxDel; fVScrollEnable = cyDel; }
EnableScrollBar(ghwndPane[iPane], SB_HORZ, (cxDel && !bDesc) ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH);
EnableScrollBar(ghwndPane[iPane], SB_VERT, (cyDel && !bDesc) ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH);
// Ensure that the thumb is at a meaningful position
if (GetScrollPos(ghwndPane[iPane], SB_HORZ) > cxDel) SetScrollPos(ghwndPane[iPane], SB_HORZ, cxDel, TRUE);
if (GetScrollPos(ghwndPane[iPane], SB_VERT) > cyDel) SetScrollPos(ghwndPane[iPane], SB_VERT, cyDel, TRUE); }
static VOID Undo( INT iPane ) { DWORD ot; LPPICT lppict; LPVOID lpobjTemp; INT ptyTemp;
if (gpty[iPane] == PICTURE) { lppict = glpobj[iPane];
// Close the old object
if (lppict->lpObject) { OleQueryType(lppict->lpObject, &ot); if (ot != OT_STATIC) Error(OleClose(lppict->lpObject)); }
OleRename(lppict->lpObject, gszTemp); }
if (gptyUndo[iPane] == PICTURE) { lppict = glpobjUndo[iPane];
// Try to reconnect the new object if it's a link
if (lppict->lpObject) { OleQueryType(lppict->lpObject, &ot); if (ot == OT_LINK && Error(OleReconnect(lppict->lpObject))) ErrorMessage(E_FAILED_TO_RECONNECT_OBJECT); }
OleRename(lppict->lpObject, gszCaption[iPane]); }
if (gpty[iPane] == PICTURE) { CHAR szUndoName[CBMESSAGEMAX];
lppict = glpobj[iPane]; if(SUCCEEDED(StringCchPrintf(szUndoName, ARRAYSIZE(szUndoName), szUndo, gszCaption[iPane]))) { OleRename(lppict->lpObject, szUndoName); } }
// Handle the buttons and enable/disable scroll bars
// Going from picture to non-picture, disable all special things
if (gptyUndo[iPane] != PICTURE && gpty[iPane] == PICTURE) { if (iPane == CONTENT) { CheckRadioButton(ghwndBar[CONTENT], IDM_PICT, IDM_DESC, IDM_DESC); EnableWindow(ghwndPict, FALSE); }
EnableScrollBar(ghwndPane[iPane], SB_HORZ, ESB_DISABLE_BOTH); EnableScrollBar(ghwndPane[iPane], SB_VERT, ESB_DISABLE_BOTH); }
if (gptyUndo[iPane] == PICTURE || gptyUndo[iPane] == CMDLINK) { SendMessage(ghwndPane[iPane], WM_FIXSCROLL, 0, 0L);
if (gptyUndo[iPane] == PICTURE) { // Going from non-picture to picture, enable button
if (gpty[iPane] != PICTURE && iPane == CONTENT) EnableWindow(ghwndPict, TRUE); } }
lpobjTemp = glpobj[iPane]; glpobj[iPane] = glpobjUndo[iPane]; glpobjUndo[iPane] = lpobjTemp;
ptyTemp = gpty[iPane]; gpty[iPane] = gptyUndo[iPane]; gptyUndo[iPane] = ptyTemp;
InvalidateRect(ghwndPane[iPane], NULL, TRUE); Dirty(); }
static VOID CalcWindows( BOOL fFirst ) { if (fFirst) { // Figure out the length of the text strings, and all dimensions
HDC hdc = GetWindowDC(ghwndFrame); if (hdc) { cxBorder = GetSystemMetrics(SM_CXBORDER); cyBorder = GetSystemMetrics(SM_CYBORDER); cxFudge = cxBorder * 2; cyFudge = cyBorder * 2; cxSplit = cxBorder * 4;
if (gbDBCS) { /* #3963 13-Dec-93 v-katsuy */ /* ORIGINALBUG! Window width calculated for just "&Picture".
* This width should be calculate * [Radiobutton] + [Text](not include '&'). */ CHAR szTemp[CBMESSAGEMAX]; LPSTR lpText, lpTemp;
for (lpText = szPicture, lpTemp = szTemp; *lpText; ) { if (*lpText == '&') lpText++; else *lpTemp++ = *lpText++; } *lpTemp = 0; cxPict = GetTextLen(hdc, szTemp) + cxFudge * 2 + GetSystemMetrics(SM_CXSIZE); // for radiobutton
for (lpText = szDescription, lpTemp = szTemp; *lpText; ) { if (*lpText == '&') lpText++; else *lpTemp++ = *lpText++; } *lpTemp = 0; cxDesc = GetTextLen(hdc, szTemp) + GetSystemMetrics(SM_CXSIZE); // for radiobutton
} else { cxPict = GetTextLen(hdc, szPicture) + cxFudge * 2; cxDesc = GetTextLen(hdc, szDescription); }
cxView = GetTextLen(hdc, szView); cxInsertIcon = GetTextLen(hdc, szInsertIcon) + cxFudge;
cxMin[CONTENT] = cxPict + cxDesc + cxView + GetTextLen(hdc, gszCaption[CONTENT]) + cxFudge; cxMin[APPEARANCE] = cxInsertIcon + GetTextLen(hdc, gszCaption[APPEARANCE]) + cxFudge; cyHeight = GetSystemMetrics(SM_CYMENU) + cyFudge * 2; ReleaseDC(ghwndFrame, hdc);
cxMinWidth = cxMin[APPEARANCE] + cxMin[CONTENT] + cxSplit + GetSystemMetrics(SM_CXFRAME) + cxFudge;
// Compute all the window sizes that we can
SetWindowPos(ghwndFrame, 0, 0, 0, cxMinWidth + cxFudge * 20, cxMinWidth * 7 / 18, SWP_NOMOVE | SWP_NOZORDER); SetWindowPos(hwndInsertIcon, 0, 0, 0, cxInsertIcon - cxFudge, GetSystemMetrics(SM_CYMENU), SWP_NOMOVE | SWP_NOZORDER); SetWindowPos(hwndView, 0, 0, 0, cxView, cyHeight - cyFudge, SWP_NOMOVE | SWP_NOZORDER); SetWindowPos(ghwndPict, 0, 0, 0, (cxPict - cxFudge) << 1, GetSystemMetrics(SM_CYMENU), SWP_NOMOVE | SWP_NOZORDER); SetWindowPos(hwndDesc, 0, 0, 0, cxDesc, GetSystemMetrics(SM_CYMENU), SWP_NOMOVE | SWP_NOZORDER); } } else { RECT rc;
GetClientRect(ghwndFrame, &rc);
// Move the windows to the appropriate locations
SetWindowPos(ghwndBar[APPEARANCE], 0, 0, 0, xSplit - cxSplit / 2 - cxBorder, cyHeight, SWP_NOZORDER);
SetWindowPos(ghwndBar[CONTENT], 0, xSplit + cxSplit / 2 + cxBorder, 0, rc.right - (xSplit + cxSplit / 2) + 1 - cxBorder, cyHeight, SWP_NOZORDER);
SetWindowPos(ghwndPane[APPEARANCE], 0, -cxBorder, cyHeight, cxBorder + xSplit - cxSplit / 2, rc.bottom + cyBorder - cyHeight, SWP_NOZORDER);
SetWindowPos(ghwndPane[CONTENT], 0, xSplit + cxSplit / 2, cyHeight, cxBorder + rc.right - (xSplit + cxSplit / 2) + 1, rc.bottom + cyBorder - cyHeight, SWP_NOZORDER); } }
static INT Constrain( INT x, INT right ) { // Constrain the splitter bar...
if (x < cxMin[APPEARANCE] + cxSplit / 2 - 1) return cxMin[APPEARANCE] + cxSplit / 2 - 1; else if (x > (right - cxMin[CONTENT] - cxSplit / 2 + 1)) return right - cxMin[CONTENT] - cxSplit / 2 + 1;
return x; }
/* CopyOther() - Copies the picture in appearance pane
* * Returns: none */ static VOID CopyOther( VOID ) { HANDLE hdata;
if (OpenClipboard(ghwndFrame)) { Hourglass(TRUE); EmptyClipboard();
if (hdata = GetMF()) SetClipboardData(CF_METAFILEPICT, hdata);
CloseClipboard(); Hourglass(FALSE); } }
VOID DeletePaneObject( LPVOID lpobj, INT objType ) { switch (objType) { case CMDLINK: CmlDelete(lpobj); break;
case PEMBED: EmbDelete(lpobj); break;
case ICON: IconDelete(lpobj); break;
case PICTURE: PicDelete(lpobj); break; } }
|