1512 lines
44 KiB
C
1512 lines
44 KiB
C
/* 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;
|
|
}
|
|
}
|