Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1511 lines
45 KiB

  1. /* pane.c - This file contains the multi-pane handling routines.
  2. *
  3. * Copyright (c) 1991-, Microsoft Corporation.
  4. * All rights reserved.
  5. */
  6. #include "packager.h"
  7. #include <shellapi.h>
  8. #include "dialogs.h"
  9. //#define OLESVR_SUPPORT /* enable support for OLE server files */
  10. #define DRAG_EMBED 2 // Ctrl + Drag
  11. #define DRAG_LINK 6 // Ctrl + Shift + Drag
  12. static HBRUSH hbrBlack; // Black brush
  13. static HCURSOR hcurSplit;
  14. static HWND hwndDesc;
  15. static HWND hwndInsertIcon = NULL;
  16. static HWND hwndView = NULL;
  17. static INT cxBorder; // WS_BORDER border width
  18. static INT cyBorder;
  19. static INT cxFudge = 0; // Fudge factors for good appearance
  20. static INT cyFudge = 0;
  21. static INT cxMinWidth;
  22. static INT cxView;
  23. static INT cxSplit; // Splitter bar width
  24. static INT cxPict;
  25. static INT cxDesc;
  26. static INT cxInsertIcon;
  27. static INT cxMin[CCHILDREN];
  28. static INT cyHeight;
  29. static INT xSplit = 0;
  30. static CHAR szButton[] = "button";
  31. static CHAR szStatic[] = "static";
  32. static CHAR szPaneClass[] = "PaneClass";
  33. static CHAR szSubtitleClass[] = "SubTitleClass";
  34. static CHAR szDescription[CBMESSAGEMAX];
  35. static CHAR szView[CBMESSAGEMAX];
  36. static CHAR szPicture[CBMESSAGEMAX];
  37. static CHAR szInsertIcon[CBMESSAGEMAX];
  38. static CHAR szDropFile[CBPATHMAX];
  39. static BOOL fHScrollEnable = FALSE;
  40. static BOOL fVScrollEnable = FALSE;
  41. static BOOL MakeWindows(VOID);
  42. static INT GetTextLen(HDC hdc, LPSTR lpstr);
  43. static VOID RecalibrateScroll(INT iPane, DWORD lParam);
  44. static VOID Undo(INT iPane);
  45. static VOID CalcWindows(BOOL fFirst);
  46. static INT Constrain(INT x, INT right);
  47. static VOID CopyOther(VOID);
  48. /* InitPaneClasses() - Do application "global" initialization.
  49. *
  50. * This function registers the window classes used by the application.
  51. * Returns: TRUE if successful.
  52. */
  53. BOOL
  54. InitPaneClasses(
  55. VOID
  56. )
  57. {
  58. WNDCLASS wc;
  59. wc.style = 0;
  60. wc.lpfnWndProc = SubtitleWndProc;
  61. wc.cbClsExtra = 0;
  62. wc.cbWndExtra = 0;
  63. wc.hInstance = ghInst;
  64. wc.hIcon = LoadIcon(ghInst, MAKEINTRESOURCE(ID_APPLICATION));
  65. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  66. wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
  67. wc.lpszMenuName = MAKEINTRESOURCE(ID_APPLICATION);
  68. wc.lpszClassName = szSubtitleClass;
  69. if (!RegisterClass(&wc))
  70. return FALSE;
  71. wc.style = CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW;
  72. wc.lpfnWndProc = PaneWndProc;
  73. wc.cbClsExtra = 0;
  74. // Reserve space for the item specific data handle
  75. wc.cbWndExtra = sizeof(LPVOID);
  76. wc.hInstance = ghInst;
  77. wc.hIcon = NULL;
  78. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  79. wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
  80. wc.lpszMenuName = NULL;
  81. wc.lpszClassName = szPaneClass;
  82. if (!RegisterClass(&wc))
  83. return FALSE;
  84. return TRUE;
  85. }
  86. /* InitPanes() - Handles the instance-specific initialization.
  87. *
  88. * This function creates the main application window.
  89. * Returns: TRUE if successful.
  90. */
  91. BOOL
  92. InitPanes(
  93. VOID
  94. )
  95. {
  96. LOGFONT lf;
  97. CHARSETINFO csinfo;
  98. LCID lcid = GetThreadLocale();
  99. DWORD dwCp = GetACP();
  100. hbrBlack = GetStockObject(BLACK_BRUSH);
  101. hcurSplit = LoadCursor(ghInst, MAKEINTRESOURCE(SPLIT));
  102. gcxIcon = GetSystemMetrics(SM_CXICON);
  103. gcyIcon = GetSystemMetrics(SM_CYICON);
  104. SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, FALSE);
  105. SystemParametersInfo(SPI_ICONHORIZONTALSPACING, 0, &gcxArrange, FALSE);
  106. SystemParametersInfo(SPI_ICONVERTICALSPACING, 0, &gcyArrange, FALSE);
  107. // ANSI app needs to make sure it has the right charset for text rendering
  108. if (TranslateCharsetInfo(&dwCp, &csinfo, TCI_SRCCODEPAGE))
  109. lf.lfCharSet = (BYTE) csinfo.ciCharset;
  110. // Lock down font size to 8 point size since we won't adjust window size
  111. lf.lfHeight = -MulDiv(8, giYppli, 72);
  112. lf.lfWidth = 0;
  113. ghfontTitle = CreateFontIndirect(&lf);
  114. if (PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_CHINESE ||
  115. PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_JAPANESE)
  116. lf.lfWeight = FW_NORMAL;
  117. else
  118. lf.lfWeight = FW_BOLD;
  119. ghfontChild = CreateFontIndirect(&lf);
  120. if (!(ghfontTitle || ghfontChild))
  121. {
  122. if (ghfontTitle)
  123. DeleteObject(ghfontTitle);
  124. return FALSE;
  125. }
  126. LoadString(ghInst, IDS_CONTENT, gszCaption[CONTENT], CBMESSAGEMAX);
  127. LoadString(ghInst, IDS_VIEW, szView, CBMESSAGEMAX);
  128. LoadString(ghInst, IDS_DESCRIPTION, szDescription, CBMESSAGEMAX);
  129. LoadString(ghInst, IDS_PICTURE, szPicture, CBMESSAGEMAX);
  130. LoadString(ghInst, IDS_APPEARANCE, gszCaption[APPEARANCE], CBMESSAGEMAX);
  131. LoadString(ghInst, IDS_INSERTICON, szInsertIcon, CBMESSAGEMAX);
  132. // Create the window panes
  133. if (!MakeWindows())
  134. return FALSE;
  135. CalcWindows(TRUE);
  136. // Give the focus to the content pane
  137. PostMessage(ghwndPane[CONTENT], WM_LBUTTONDOWN, 0, 0L);
  138. return TRUE;
  139. }
  140. /* EndPaneInstance() - Instance-specific termination code.
  141. */
  142. VOID
  143. EndPanes(
  144. VOID
  145. )
  146. {
  147. if (ghfontTitle)
  148. DeleteObject(ghfontTitle);
  149. if (ghfontChild)
  150. DeleteObject(ghfontChild);
  151. }
  152. /* MakeWindows() - Make the window panes.
  153. */
  154. static BOOL
  155. MakeWindows(
  156. VOID
  157. )
  158. {
  159. if (ghwndBar[CONTENT] =
  160. CreateWindow(szSubtitleClass, gszCaption[CONTENT], WS_CHILD | WS_VISIBLE,
  161. 0, 0, 0, 0, ghwndFrame, NULL, ghInst, NULL))
  162. {
  163. hwndView = CreateWindow(szStatic, szView,
  164. WS_CHILD | WS_VISIBLE | SS_LEFT | SS_CENTERIMAGE,
  165. 0, 0, 0, 0, ghwndBar[CONTENT], NULL, ghInst, NULL);
  166. hwndDesc = CreateWindow(szButton, szDescription,
  167. WS_CHILD | BS_AUTORADIOBUTTON | WS_VISIBLE | WS_GROUP,
  168. 0, 0, 0, 0, ghwndBar[CONTENT], (HMENU)IDM_DESC, ghInst, NULL);
  169. ghwndPict = CreateWindow(szButton, szPicture,
  170. WS_CHILD | BS_AUTORADIOBUTTON | WS_VISIBLE,
  171. 0, 0, 0, 0, ghwndBar[CONTENT], (HMENU)IDM_PICT, ghInst, NULL);
  172. if (hwndView && hwndDesc && ghwndPict)
  173. {
  174. // Use the appropriate dialog font
  175. SendMessage(ghwndBar[CONTENT], WM_SETFONT, (WPARAM)ghfontChild, TRUE);
  176. SendMessage(hwndView, WM_SETFONT, (WPARAM)ghfontChild, TRUE);
  177. SendMessage(hwndDesc, WM_SETFONT, (WPARAM)ghfontChild, TRUE);
  178. SendMessage(ghwndPict, WM_SETFONT, (WPARAM)ghfontChild, TRUE);
  179. CheckRadioButton(ghwndBar[CONTENT], IDM_PICT, IDM_DESC, IDM_DESC);
  180. EnableWindow(ghwndPict, FALSE);
  181. }
  182. else
  183. {
  184. goto Error;
  185. }
  186. }
  187. else
  188. {
  189. goto Error;
  190. }
  191. if (ghwndBar[APPEARANCE] =
  192. CreateWindow(szSubtitleClass, gszCaption[APPEARANCE],
  193. WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, ghwndFrame, NULL, ghInst, NULL))
  194. {
  195. hwndInsertIcon =
  196. CreateWindow(szButton, szInsertIcon,
  197. WS_CHILD | BS_PUSHBUTTON | WS_VISIBLE,
  198. 0, 0, 0, 0, ghwndBar[APPEARANCE], (HMENU)IDM_INSERTICON,
  199. ghInst, NULL);
  200. if (hwndInsertIcon)
  201. {
  202. SendMessage(ghwndBar[APPEARANCE], WM_SETFONT, (WPARAM)ghfontChild,
  203. TRUE);
  204. SendMessage(hwndInsertIcon, WM_SETFONT, (WPARAM)ghfontChild, TRUE);
  205. }
  206. else
  207. {
  208. goto Error;
  209. }
  210. }
  211. else
  212. {
  213. goto Error;
  214. }
  215. ghwndPane[APPEARANCE] =
  216. CreateWindowEx(WS_EX_CLIENTEDGE, szPaneClass, NULL,
  217. WS_BORDER | WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL,
  218. 0, 0, 0, 0, ghwndFrame, NULL, ghInst, NULL);
  219. ghwndPane[CONTENT] =
  220. CreateWindowEx(WS_EX_CLIENTEDGE, szPaneClass, NULL,
  221. WS_BORDER | WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL,
  222. 0, 0, 0, 0, ghwndFrame, NULL, ghInst, NULL);
  223. if (!ghwndPane[APPEARANCE] || !ghwndPane[CONTENT])
  224. goto Error;
  225. EnableScrollBar(ghwndPane[APPEARANCE], SB_HORZ, ESB_DISABLE_BOTH);
  226. EnableScrollBar(ghwndPane[APPEARANCE], SB_VERT, ESB_DISABLE_BOTH);
  227. EnableScrollBar(ghwndPane[CONTENT], SB_HORZ, ESB_DISABLE_BOTH);
  228. EnableScrollBar(ghwndPane[CONTENT], SB_VERT, ESB_DISABLE_BOTH);
  229. DragAcceptFiles(ghwndPane[CONTENT], TRUE);
  230. return TRUE;
  231. Error:
  232. if (ghwndBar[CONTENT])
  233. {
  234. if (hwndView)
  235. DestroyWindow(hwndView);
  236. if (hwndDesc)
  237. DestroyWindow(hwndDesc);
  238. if (ghwndPict)
  239. DestroyWindow(ghwndPict);
  240. DestroyWindow(ghwndBar[CONTENT]);
  241. }
  242. if (ghwndBar[APPEARANCE])
  243. {
  244. if (hwndInsertIcon)
  245. DestroyWindow(hwndInsertIcon);
  246. DestroyWindow(ghwndBar[APPEARANCE]);
  247. }
  248. if (ghwndPane[APPEARANCE])
  249. DestroyWindow(ghwndPane[APPEARANCE]);
  250. if (ghwndPane[CONTENT])
  251. DestroyWindow(ghwndPane[CONTENT]);
  252. return FALSE;
  253. }
  254. /* SubtitleWndProc() - "Appearance" and "Content" bar window procedure.
  255. */
  256. LRESULT CALLBACK
  257. SubtitleWndProc(
  258. HWND hWnd,
  259. UINT msg,
  260. WPARAM wParam,
  261. LPARAM lParam
  262. )
  263. {
  264. PAINTSTRUCT ps;
  265. RECT rcCaption;
  266. INT iPane;
  267. iPane = (hWnd == ghwndBar[CONTENT]);
  268. switch (msg)
  269. {
  270. case WM_COMMAND:
  271. switch (LOWORD(wParam))
  272. {
  273. case IDM_INSERTICON:
  274. Raise(APPEARANCE);
  275. DeletePane(APPEARANCE, FALSE);
  276. if (gptyUndo[APPEARANCE] != ICON)
  277. glpobj[APPEARANCE] = IconCreateFromFile("");
  278. else
  279. glpobj[APPEARANCE] = IconClone(glpobjUndo[APPEARANCE]);
  280. if (glpobj[APPEARANCE])
  281. gpty[APPEARANCE] = ICON;
  282. if (glpobj[APPEARANCE] && IconDialog(glpobj[APPEARANCE]))
  283. {
  284. InvalidateRect(ghwndPane[APPEARANCE], NULL, TRUE);
  285. Dirty();
  286. }
  287. else
  288. {
  289. IconDelete(glpobj[APPEARANCE]);
  290. gpty[APPEARANCE] = NOTHING;
  291. glpobj[APPEARANCE] = NULL;
  292. SendMessage(ghwndPane[APPEARANCE], WM_COMMAND,
  293. IDM_UNDO, 0);
  294. }
  295. break;
  296. case IDM_DESC:
  297. if (!IsDlgButtonChecked(ghwndBar[CONTENT], IDM_DESC))
  298. CheckRadioButton(ghwndBar[CONTENT], IDM_PICT,
  299. IDM_DESC, IDM_DESC);
  300. if (fHScrollEnable)
  301. EnableScrollBar(ghwndPane[iPane], SB_HORZ,
  302. ESB_DISABLE_BOTH);
  303. if (fVScrollEnable)
  304. EnableScrollBar(ghwndPane[iPane], SB_VERT,
  305. ESB_DISABLE_BOTH);
  306. InvalidateRect(ghwndPane[CONTENT], NULL, TRUE);
  307. goto defProcess;
  308. case IDM_PICT:
  309. if (!IsDlgButtonChecked(ghwndBar[CONTENT], IDM_PICT)
  310. && IsWindowEnabled(GetDlgItem(ghwndBar[CONTENT],
  311. IDM_PICT)))
  312. CheckRadioButton(ghwndBar[CONTENT], IDM_PICT,
  313. IDM_DESC, IDM_PICT);
  314. if (fHScrollEnable)
  315. EnableScrollBar(ghwndPane[iPane], SB_HORZ,
  316. ESB_ENABLE_BOTH);
  317. if (fVScrollEnable)
  318. EnableScrollBar(ghwndPane[iPane], SB_VERT,
  319. ESB_ENABLE_BOTH);
  320. InvalidateRect(ghwndPane[CONTENT], NULL, TRUE);
  321. // Fall through
  322. default:
  323. defProcess:
  324. if (GetTopWindow(ghwndFrame) != ghwndPane[iPane])
  325. {
  326. if (gbDBCS)
  327. {
  328. /* 4-Oct-93 #2701 v-katsuy */
  329. //win31#1203: 12/26/92:fixing Focus Line Scroll
  330. //delete Focus Rect on another pane
  331. InvalidateRect(ghwndPane[APPEARANCE], NULL, TRUE);
  332. }
  333. BringWindowToTop(ghwndPane[iPane]);
  334. InvalidateRect(ghwndBar[APPEARANCE], NULL, TRUE);
  335. InvalidateRect(ghwndBar[CONTENT], NULL, TRUE);
  336. if (LOWORD(wParam) == IDM_PICT
  337. || LOWORD(wParam) == IDM_DESC)
  338. UpdateWindow(ghwndPane[CONTENT]);
  339. }
  340. }
  341. break;
  342. case WM_LBUTTONDOWN:
  343. if (GetTopWindow(ghwndFrame) != ghwndPane[iPane])
  344. SendMessage(ghwndPane[iPane], WM_LBUTTONDOWN, 0, 0);
  345. break;
  346. case WM_PAINT:
  347. {
  348. HFONT hfontOld;
  349. GetClientRect(hWnd, &rcCaption);
  350. BeginPaint(hWnd, &ps);
  351. if (GetTopWindow(ghwndFrame) == ghwndPane[iPane])
  352. {
  353. SetTextColor(ps.hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
  354. SetBkColor(ps.hdc, GetSysColor(COLOR_HIGHLIGHT));
  355. }
  356. else
  357. {
  358. SetTextColor(ps.hdc, GetSysColor(COLOR_WINDOWTEXT));
  359. SetBkColor(ps.hdc, GetSysColor(COLOR_WINDOW));
  360. }
  361. hfontOld = SelectObject(ps.hdc, ghfontChild);
  362. rcCaption.left += cxFudge;
  363. DrawText(ps.hdc, gszCaption[iPane], -1, &rcCaption,
  364. DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_NOCLIP);
  365. SelectObject(ps.hdc, hfontOld);
  366. EndPaint(hWnd, &ps);
  367. }
  368. break;
  369. case WM_SIZE:
  370. if (iPane == APPEARANCE)
  371. {
  372. if (hwndInsertIcon)
  373. {
  374. GetClientRect(hWnd, &rcCaption);
  375. SetWindowPos(hwndInsertIcon, 0,
  376. rcCaption.right - cxInsertIcon, cyFudge, 0, 0,
  377. SWP_NOSIZE | SWP_NOZORDER);
  378. InvalidateRect(ghwndBar[APPEARANCE], NULL, TRUE);
  379. }
  380. }
  381. else
  382. {
  383. if (hwndView)
  384. {
  385. BOOL bChinese = PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale())) == LANG_CHINESE;
  386. GetClientRect(hWnd, &rcCaption);
  387. SetWindowPos(hwndView, 0,
  388. bChinese ?
  389. rcCaption.right - cxDesc - cxPict - cxView - 15 :
  390. rcCaption.right - cxDesc - cxPict - cxView,
  391. 0, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
  392. SetWindowPos(hwndDesc, 0,
  393. rcCaption.right - cxDesc - cxPict,
  394. cyFudge, 0, 0,
  395. SWP_NOSIZE | SWP_NOZORDER);
  396. SetWindowPos(ghwndPict, 0,
  397. rcCaption.right - cxPict,
  398. cyFudge, 0, 0,
  399. SWP_NOSIZE | SWP_NOZORDER);
  400. InvalidateRect(ghwndBar[CONTENT], NULL, TRUE);
  401. }
  402. }
  403. break;
  404. default:
  405. return DefWindowProc(hWnd, msg, wParam, lParam);
  406. }
  407. return 0L;
  408. }
  409. static INT
  410. GetTextLen(
  411. HDC hdc,
  412. LPSTR lpstr
  413. )
  414. {
  415. SIZE Size;
  416. GetTextExtentPoint32(hdc, lpstr, lstrlen(lpstr), &Size);
  417. return Size.cx + (cxFudge * 2);
  418. }
  419. LRESULT CALLBACK
  420. PaneWndProc(
  421. HWND hwnd,
  422. UINT msg,
  423. WPARAM wParam,
  424. LPARAM lParam
  425. )
  426. {
  427. BOOL fFocus;
  428. LPVOID lpobjTemp;
  429. PAINTSTRUCT ps;
  430. RECT rc;
  431. CHAR szFile[CBPATHMAX];
  432. INT iOld;
  433. INT iPane;
  434. INT iPos;
  435. INT Max;
  436. INT Min;
  437. INT nBar;
  438. iPane = (hwnd == ghwndPane[CONTENT]);
  439. switch (msg)
  440. {
  441. case WM_HSCROLL:
  442. case WM_VSCROLL:
  443. // If not the content pane in picture mode, break
  444. if (gpty[iPane] == PICTURE
  445. && iPane == CONTENT
  446. && !IsDlgButtonChecked(ghwndBar[CONTENT], IDM_PICT))
  447. break;
  448. // Can't scroll anything but cmd line and picture
  449. if (gpty[iPane] != PICTURE && gpty[iPane] != CMDLINK)
  450. break;
  451. nBar = (msg == WM_HSCROLL ? SB_HORZ : SB_VERT);
  452. iOld = iPos = GetScrollPos(hwnd, nBar);
  453. switch (LOWORD(wParam))
  454. {
  455. case SB_LINEUP:
  456. iPos--;
  457. break;
  458. case SB_LINEDOWN:
  459. iPos++;
  460. break;
  461. case SB_PAGEUP:
  462. case SB_PAGEDOWN:
  463. GetClientRect(hwnd, &rc);
  464. if (LOWORD(wParam) == SB_PAGEUP)
  465. iPos -= (rc.bottom - rc.top + 1);
  466. else
  467. iPos += (rc.bottom - rc.top + 1);
  468. break;
  469. case SB_THUMBPOSITION:
  470. iPos = (INT)HIWORD(wParam);
  471. break;
  472. }
  473. // Make sure that iPos is in the range
  474. GetScrollRange(hwnd, nBar, &Min, &Max);
  475. if (iPos < Min)
  476. iPos = Min;
  477. if (iPos > Max)
  478. iPos = Max;
  479. SetScrollPos(hwnd, nBar, iPos, TRUE);
  480. if (msg == WM_HSCROLL)
  481. ScrollWindow(hwnd, iOld - iPos, 0, NULL, NULL);
  482. else
  483. ScrollWindow(hwnd, 0, iOld - iPos, NULL, NULL);
  484. UpdateWindow(hwnd);
  485. break;
  486. case WM_LBUTTONDOWN:
  487. if (GetTopWindow(ghwndFrame) != hwnd)
  488. {
  489. BringWindowToTop(hwnd);
  490. InvalidateRect(ghwndBar[APPEARANCE], NULL, TRUE);
  491. InvalidateRect(ghwndBar[CONTENT], NULL, TRUE);
  492. InvalidateRect(ghwndPane[APPEARANCE], NULL, TRUE);
  493. InvalidateRect(ghwndPane[CONTENT], NULL, TRUE);
  494. }
  495. break;
  496. case WM_PAINT:
  497. GetClientRect(hwnd, &rc);
  498. BeginPaint(hwnd, &ps);
  499. if (fFocus = (ghwndPane[iPane] == GetTopWindow(ghwndFrame)))
  500. {
  501. SetTextColor(ps.hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
  502. SetBkColor(ps.hdc, GetSysColor(COLOR_HIGHLIGHT));
  503. }
  504. else
  505. {
  506. SetTextColor(ps.hdc, GetSysColor(COLOR_WINDOWTEXT));
  507. SetBkColor(ps.hdc, GetSysColor(COLOR_WINDOW));
  508. }
  509. switch (gpty[iPane])
  510. {
  511. case CMDLINK:
  512. CmlDraw(glpobj[iPane], ps.hdc, &rc,
  513. GetScrollPos(hwnd, SB_HORZ), fFocus);
  514. break;
  515. case PEMBED:
  516. EmbDraw(glpobj[iPane], ps.hdc, &rc, fFocus);
  517. break;
  518. case ICON:
  519. IconDraw(glpobj[iPane], ps.hdc, &rc, fFocus, 0, 0);
  520. break;
  521. case PICTURE:
  522. PicDraw(glpobj[iPane], ps.hdc, &rc,
  523. GetScrollPos(hwnd, SB_HORZ),
  524. GetScrollPos(hwnd, SB_VERT),
  525. hwnd == ghwndPane[APPEARANCE] ||
  526. IsDlgButtonChecked(ghwndBar[CONTENT], IDM_PICT), fFocus);
  527. break;
  528. default:
  529. FillRect(ps.hdc, &rc, ghbrBackground);
  530. break;
  531. }
  532. EndPaint(hwnd, &ps);
  533. break;
  534. case WM_FIXSCROLL:
  535. GetClientRect(hwnd, &rc);
  536. lParam = ((DWORD)rc.bottom << 16) | (DWORD)rc.right;
  537. // Fall through
  538. case WM_SIZE:
  539. if (gpty[iPane] == PICTURE || gpty[iPane] == CMDLINK)
  540. RecalibrateScroll(iPane, (DWORD)lParam);
  541. break;
  542. case WM_DESTROY:
  543. DeletePane(iPane, TRUE);
  544. break;
  545. case WM_DROPFILES:
  546. {
  547. BYTE bKeyState = 0;
  548. // Retrieve the file name
  549. DragQueryFile((HANDLE)wParam, 0, szDropFile, CBPATHMAX);
  550. DragFinish((HANDLE)wParam);
  551. // We got dropped on, so bring ourselves to the top
  552. BringWindowToTop(ghwndFrame);
  553. BringWindowToTop(hwnd);
  554. // See what the user wants us to do
  555. bKeyState = ((GetKeyState(VK_SHIFT) < 0) << 2)
  556. | ((GetKeyState(VK_CONTROL) < 0) << 1)
  557. | ((GetKeyState(VK_MENU) < 0));
  558. switch (bKeyState)
  559. {
  560. case DRAG_LINK:
  561. PostMessage(hwnd, WM_COMMAND, IDM_LINKFILE, 0L);
  562. break;
  563. case DRAG_EMBED:
  564. default:
  565. PostMessage(hwnd, WM_COMMAND, IDM_EMBEDFILE, 0L);
  566. break;
  567. }
  568. break;
  569. }
  570. case WM_LBUTTONDBLCLK:
  571. // Alt + Double Click = Properties
  572. if (gpty[iPane] == PICTURE && GetKeyState(VK_MENU) < 0)
  573. {
  574. wParam = IDM_LINKS;
  575. }
  576. else
  577. {
  578. if (gpty[iPane] == PEMBED)
  579. {
  580. //
  581. // If the server is a OLE server, we want to activate in
  582. // OLE fashion. But from users perspective it should not
  583. // look like an object. So for non-objects double-click
  584. // implies show the server. We should try to do the same
  585. // thing while editing ole server files.
  586. //
  587. wParam = IDD_EDIT;
  588. }
  589. else
  590. {
  591. wParam = IDD_PLAY;
  592. }
  593. }
  594. msg = WM_COMMAND;
  595. lParam = 0;
  596. // Fall through
  597. case WM_COMMAND:
  598. switch (LOWORD(wParam))
  599. {
  600. case IDM_COPY:
  601. case IDM_CUT:
  602. switch (gpty[iPane])
  603. {
  604. case PICTURE:
  605. PicCopy(glpobj[iPane]);
  606. default:
  607. if (iPane == APPEARANCE)
  608. CopyOther();
  609. break;
  610. }
  611. if (LOWORD(wParam) == IDM_COPY)
  612. break;
  613. // Fall through to delete the selection
  614. case IDM_CLEAR:
  615. DeletePane(iPane, FALSE);
  616. break;
  617. case IDM_LINKS:
  618. {
  619. LONG objtype;
  620. OleQueryType(((LPPICT)glpobj[iPane])->lpObject, &objtype);
  621. if (objtype == OT_LINK)
  622. DialogBoxAfterBlock(MAKEINTRESOURCE(DTPROP),
  623. ghwndPane[iPane], fnProperties);
  624. break;
  625. }
  626. case IDM_LINKFILE:
  627. if(SUCCEEDED(StringCchCopy(szFile, ARRAYSIZE(szFile), szDropFile)))
  628. {
  629. wParam = IDM_PASTELINK;
  630. goto CreateFromFile;
  631. }
  632. break;
  633. case IDM_EMBEDFILE:
  634. if(SUCCEEDED(StringCchCopy(szFile, ARRAYSIZE(szFile), szDropFile)))
  635. {
  636. wParam = IDM_PASTE;
  637. goto CreateFromFile;
  638. }
  639. break;
  640. case IDM_PASTE:
  641. case IDM_PASTELINK:
  642. // Try to paste a file name from the File Manager
  643. if (iPane == CONTENT)
  644. {
  645. HANDLE hdata;
  646. LPSTR lpstrFile;
  647. if (IsClipboardFormatAvailable(gcfFileName))
  648. {
  649. if (!OpenClipboard(ghwndFrame))
  650. break;
  651. if (!(hdata = GetClipboardData(gcfFileName)) || !(lpstrFile =
  652. GlobalLock(hdata)))
  653. {
  654. CloseClipboard();
  655. break;
  656. }
  657. StringCchCopy(szFile, ARRAYSIZE(szFile), lpstrFile);
  658. GlobalUnlock(hdata);
  659. CloseClipboard();
  660. CreateFromFile:
  661. #ifdef OLESVR_SUPPORT
  662. if (IsOleServerDoc (szFile))
  663. {
  664. lpobjTemp = PicFromFile((wParam == IDM_PASTE),
  665. szFile);
  666. if (!lpobjTemp)
  667. {
  668. ErrorMessage(E_GET_FROM_CLIPBOARD_FAILED);
  669. break;
  670. }
  671. goto StuffNewObject;
  672. }
  673. else
  674. {
  675. #endif
  676. DeletePane(CONTENT, FALSE);
  677. if (wParam == IDM_PASTE)
  678. {
  679. if (glpobj[CONTENT] = EmbCreate(szFile))
  680. gpty[CONTENT] = PEMBED;
  681. }
  682. else
  683. {
  684. if (glpobj[CONTENT] =
  685. CmlCreateFromFilename(szFile, TRUE))
  686. gpty[CONTENT] = CMDLINK;
  687. }
  688. #ifdef OLESVR_SUPPORT
  689. }
  690. #endif
  691. InvalidateRect(ghwndPane[CONTENT], NULL, TRUE);
  692. Dirty();
  693. if (!gpty[APPEARANCE])
  694. {
  695. if (glpobj[APPEARANCE] =
  696. IconCreateFromFile(szFile))
  697. {
  698. gpty[APPEARANCE] = ICON;
  699. InvalidateRect(ghwndPane[APPEARANCE],
  700. NULL, TRUE);
  701. }
  702. }
  703. break;
  704. }
  705. }
  706. // Not a file name, try to paste an OLE object
  707. if (!(lpobjTemp = PicPaste(LOWORD(wParam) == IDM_PASTE,
  708. gszCaption[iPane])))
  709. {
  710. ErrorMessage(E_GET_FROM_CLIPBOARD_FAILED);
  711. break;
  712. }
  713. #ifdef OLESVR_SUPPORT
  714. StuffNewObject:
  715. #endif
  716. DeletePane(iPane, FALSE);
  717. glpobj[iPane] = lpobjTemp;
  718. gpty[iPane] = PICTURE;
  719. SendMessage(ghwndPane[iPane], WM_FIXSCROLL, 0, 0L);
  720. InvalidateRect(ghwndPane[iPane], NULL, TRUE);
  721. Dirty();
  722. if (iPane == CONTENT)
  723. {
  724. EnableWindow(ghwndPict, TRUE);
  725. if (!gpty[APPEARANCE])
  726. {
  727. if (glpobj[APPEARANCE] = IconCreateFromObject(
  728. ((LPPICT)glpobj[iPane])->lpObject))
  729. {
  730. gpty[APPEARANCE] = ICON;
  731. InvalidateRect(ghwndPane[APPEARANCE], NULL, TRUE);
  732. }
  733. }
  734. }
  735. Dirty();
  736. break;
  737. case IDD_EDIT: /* Edit the icon form */
  738. case IDD_PLAY:
  739. switch (gpty[iPane])
  740. {
  741. case CMDLINK:
  742. CmlActivate(glpobj[iPane]);
  743. break;
  744. case PEMBED:
  745. EmbActivate(glpobj[iPane], LOWORD(wParam));
  746. break;
  747. case PICTURE:
  748. PicActivate(glpobj[iPane], LOWORD(wParam));
  749. break;
  750. default:
  751. break;
  752. }
  753. break;
  754. case IDD_UPDATE: /* Update the (link) object */
  755. if (gpty[iPane] == PICTURE)
  756. PicUpdate(glpobj[iPane]);
  757. break;
  758. case IDD_FREEZE: /* Make the object static */
  759. if (gpty[iPane] == PICTURE)
  760. PicFreeze(glpobj[iPane]);
  761. break;
  762. case IDD_CHANGE:
  763. if (gpty[iPane] == PICTURE)
  764. PicChangeLink(glpobj[iPane]);
  765. break;
  766. case IDM_UNDO:
  767. Undo(iPane);
  768. break;
  769. case IDD_AUTO: /* Change the (link) update options */
  770. case IDD_MANUAL:
  771. if (gpty[iPane] == PICTURE
  772. && !PicSetUpdateOptions(glpobj[iPane], LOWORD(wParam)))
  773. break;
  774. case IDM_LINKDONE: /* The link update has completed */
  775. PostMessage(ghwndError, WM_REDRAW, 0, 0L);
  776. break;
  777. default:
  778. break;
  779. }
  780. break;
  781. default:
  782. return (DefWindowProc(hwnd, msg, wParam, lParam));
  783. }
  784. return 0;
  785. }
  786. LRESULT CALLBACK
  787. SplitterFrame(
  788. HWND hWnd,
  789. UINT msg,
  790. WPARAM wParam,
  791. LPARAM lParam
  792. )
  793. {
  794. RECT rc;
  795. switch (msg)
  796. {
  797. case WM_SIZE:
  798. if (wParam != SIZEICONIC && ghwndBar[APPEARANCE])
  799. {
  800. GetClientRect(hWnd, &rc);
  801. // Make sure the splitter bar is still valid
  802. xSplit = Constrain(xSplit, rc.right);
  803. CalcWindows(FALSE);
  804. // Invalidate the splitter bar, forcing a repaint
  805. rc.left = xSplit - cxSplit / 2 - cxBorder;
  806. rc.right = xSplit + cxSplit / 2 + cxBorder;
  807. InvalidateRect(hWnd, &rc, TRUE);
  808. }
  809. break;
  810. case WM_PAINT:
  811. {
  812. PAINTSTRUCT ps;
  813. RECT rcBlack;
  814. BeginPaint(hWnd, &ps);
  815. GetClientRect(hWnd, &rc);
  816. SetRect(&rcBlack, xSplit - cxSplit / 2 - cxBorder,
  817. rc.top, xSplit + cxSplit / 2 + cxBorder,
  818. rc.top + cyHeight + cyBorder);
  819. FillRect(ps.hdc, &rcBlack, hbrBlack);
  820. SetRect(&rcBlack, xSplit - cxSplit / 2 - cxBorder,
  821. rc.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1,
  822. xSplit + cxSplit / 2 + cxBorder,
  823. rc.bottom);
  824. FillRect(ps.hdc, &rcBlack, hbrBlack);
  825. EndPaint(hWnd, &ps);
  826. break;
  827. }
  828. case WM_GETMINMAXINFO:
  829. {
  830. LPPOINT rgpt = (LPPOINT)lParam;
  831. rgpt[3].x = cxMinWidth;
  832. rgpt[3].y = cyHeight * 6;
  833. break;
  834. }
  835. case WM_LBUTTONDOWN:
  836. {
  837. MSG msg1;
  838. INT x;
  839. INT y;
  840. INT dy;
  841. HDC hdc;
  842. HCURSOR hcurOld;
  843. if (IsIconic(hWnd))
  844. break;
  845. x = LOWORD(lParam);
  846. GetClientRect(hWnd, &rc);
  847. y = 0;
  848. dy = rc.bottom;
  849. // Constrain the splitter bar...
  850. x = Constrain(x, rc.right);
  851. hdc = GetDC(hWnd);
  852. // split bar loop
  853. PatBlt(hdc, x - cxSplit / 2, y, cxSplit, dy, PATINVERT);
  854. SetCapture(hWnd);
  855. hcurOld = SetCursor(hcurSplit);
  856. while (GetMessage(&msg1, NULL, 0, 0))
  857. {
  858. if (msg1.message >= WM_MOUSEFIRST
  859. && msg1.message <= WM_MOUSELAST)
  860. {
  861. if (msg1.message == WM_LBUTTONUP
  862. || msg1.message == WM_LBUTTONDOWN)
  863. break;
  864. if (msg1.message == WM_MOUSEMOVE)
  865. {
  866. ScreenToClient(hWnd, &msg1.pt);
  867. x = Constrain(x, rc.right);
  868. // erase old
  869. PatBlt(hdc, x - cxSplit / 2, y, cxSplit, dy,
  870. PATINVERT);
  871. // put down new
  872. x = Constrain(msg1.pt.x, rc.right);
  873. PatBlt(hdc, x - cxSplit / 2, y, cxSplit, dy,
  874. PATINVERT);
  875. }
  876. }
  877. else
  878. {
  879. DispatchMessage(&msg1);
  880. }
  881. }
  882. SetCursor(hcurOld);
  883. ReleaseCapture();
  884. // Constrain the splitter bar...
  885. x = Constrain(x, rc.right);
  886. // erase old
  887. PatBlt(hdc, x - cxSplit / 2, y, cxSplit, dy, PATINVERT);
  888. ReleaseDC(hWnd, hdc);
  889. if (msg1.wParam != VK_ESCAPE)
  890. {
  891. xSplit = x;
  892. CalcWindows(FALSE);
  893. InvalidateRect(ghwndBar[APPEARANCE], NULL, TRUE);
  894. InvalidateRect(ghwndBar[CONTENT], NULL, TRUE);
  895. }
  896. break;
  897. }
  898. default:
  899. return FALSE;
  900. }
  901. return TRUE;
  902. }
  903. VOID
  904. DeletePane(
  905. INT iPane,
  906. BOOL fDeleteUndo
  907. )
  908. {
  909. // Delete the last Undo object
  910. if (glpobjUndo[iPane])
  911. DeletePaneObject(glpobjUndo[iPane], gptyUndo[iPane]);
  912. // If we don't wish to keep an undo, delete the object too!
  913. if (fDeleteUndo)
  914. {
  915. DeletePaneObject(glpobj[iPane], gpty[iPane]);
  916. gptyUndo[iPane] = NOTHING;
  917. glpobjUndo[iPane] = NULL;
  918. }
  919. else
  920. {
  921. gptyUndo[iPane] = gpty[iPane];
  922. glpobjUndo[iPane] = glpobj[iPane];
  923. }
  924. // Handle the buttons and such
  925. if (gpty[iPane] == PICTURE || gpty[iPane] == CMDLINK)
  926. {
  927. CHAR szUndoName[CBMESSAGEMAX];
  928. EnableScrollBar(ghwndPane[iPane], SB_HORZ, ESB_DISABLE_BOTH);
  929. EnableScrollBar(ghwndPane[iPane], SB_VERT, ESB_DISABLE_BOTH);
  930. if (gpty[iPane] == PICTURE)
  931. {
  932. if (iPane == CONTENT)
  933. {
  934. CheckRadioButton(ghwndBar[CONTENT], IDM_PICT, IDM_DESC, IDM_DESC);
  935. EnableWindow(ghwndPict, FALSE);
  936. }
  937. // If the Undo object isn't deleted already, rename it
  938. if (!fDeleteUndo)
  939. {
  940. if(SUCCEEDED(StringCchPrintf(szUndoName, ARRAYSIZE(szUndoName), szUndo, gszCaption[iPane])))
  941. {
  942. OleRename(((LPPICT)glpobjUndo[iPane])->lpObject, szUndoName);
  943. }
  944. }
  945. }
  946. }
  947. glpobj[iPane] = NULL;
  948. gpty[iPane] = NOTHING;
  949. if (IsWindow(ghwndPane[iPane]))
  950. InvalidateRect(ghwndPane[iPane], NULL, TRUE);
  951. }
  952. static VOID
  953. RecalibrateScroll(
  954. INT iPane,
  955. DWORD lParam
  956. )
  957. {
  958. INT cxDel;
  959. INT cyDel;
  960. BOOL bDesc = FALSE;
  961. LPPICT lppict = (LPPICT)glpobj[iPane];
  962. // Compute the amount of scrolling possible
  963. cxDel = lppict->rc.right - lppict->rc.left - (INT)(lParam & 0xffff);
  964. cyDel = lppict->rc.bottom - lppict->rc.top - (INT)(lParam >> 16);
  965. // Normalize the scroll bar lengths
  966. if (cxDel < 0)
  967. cxDel = 0;
  968. if (cyDel < 0)
  969. cyDel = 0;
  970. if (iPane == CONTENT)
  971. {
  972. bDesc = IsDlgButtonChecked(ghwndBar[iPane], IDM_DESC);
  973. fHScrollEnable = cxDel;
  974. fVScrollEnable = cyDel;
  975. }
  976. EnableScrollBar(ghwndPane[iPane], SB_HORZ,
  977. (cxDel && !bDesc) ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH);
  978. EnableScrollBar(ghwndPane[iPane], SB_VERT,
  979. (cyDel && !bDesc) ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH);
  980. // Ensure that the thumb is at a meaningful position
  981. if (GetScrollPos(ghwndPane[iPane], SB_HORZ) > cxDel)
  982. SetScrollPos(ghwndPane[iPane], SB_HORZ, cxDel, TRUE);
  983. if (GetScrollPos(ghwndPane[iPane], SB_VERT) > cyDel)
  984. SetScrollPos(ghwndPane[iPane], SB_VERT, cyDel, TRUE);
  985. }
  986. static VOID
  987. Undo(
  988. INT iPane
  989. )
  990. {
  991. DWORD ot;
  992. LPPICT lppict;
  993. LPVOID lpobjTemp;
  994. INT ptyTemp;
  995. if (gpty[iPane] == PICTURE)
  996. {
  997. lppict = glpobj[iPane];
  998. // Close the old object
  999. if (lppict->lpObject)
  1000. {
  1001. OleQueryType(lppict->lpObject, &ot);
  1002. if (ot != OT_STATIC)
  1003. Error(OleClose(lppict->lpObject));
  1004. }
  1005. OleRename(lppict->lpObject, gszTemp);
  1006. }
  1007. if (gptyUndo[iPane] == PICTURE)
  1008. {
  1009. lppict = glpobjUndo[iPane];
  1010. // Try to reconnect the new object if it's a link
  1011. if (lppict->lpObject)
  1012. {
  1013. OleQueryType(lppict->lpObject, &ot);
  1014. if (ot == OT_LINK && Error(OleReconnect(lppict->lpObject)))
  1015. ErrorMessage(E_FAILED_TO_RECONNECT_OBJECT);
  1016. }
  1017. OleRename(lppict->lpObject, gszCaption[iPane]);
  1018. }
  1019. if (gpty[iPane] == PICTURE)
  1020. {
  1021. CHAR szUndoName[CBMESSAGEMAX];
  1022. lppict = glpobj[iPane];
  1023. if(SUCCEEDED(StringCchPrintf(szUndoName, ARRAYSIZE(szUndoName), szUndo, gszCaption[iPane])))
  1024. {
  1025. OleRename(lppict->lpObject, szUndoName);
  1026. }
  1027. }
  1028. // Handle the buttons and enable/disable scroll bars
  1029. // Going from picture to non-picture, disable all special things
  1030. if (gptyUndo[iPane] != PICTURE && gpty[iPane] == PICTURE)
  1031. {
  1032. if (iPane == CONTENT)
  1033. {
  1034. CheckRadioButton(ghwndBar[CONTENT], IDM_PICT, IDM_DESC, IDM_DESC);
  1035. EnableWindow(ghwndPict, FALSE);
  1036. }
  1037. EnableScrollBar(ghwndPane[iPane], SB_HORZ, ESB_DISABLE_BOTH);
  1038. EnableScrollBar(ghwndPane[iPane], SB_VERT, ESB_DISABLE_BOTH);
  1039. }
  1040. if (gptyUndo[iPane] == PICTURE || gptyUndo[iPane] == CMDLINK)
  1041. {
  1042. SendMessage(ghwndPane[iPane], WM_FIXSCROLL, 0, 0L);
  1043. if (gptyUndo[iPane] == PICTURE)
  1044. {
  1045. // Going from non-picture to picture, enable button
  1046. if (gpty[iPane] != PICTURE && iPane == CONTENT)
  1047. EnableWindow(ghwndPict, TRUE);
  1048. }
  1049. }
  1050. lpobjTemp = glpobj[iPane];
  1051. glpobj[iPane] = glpobjUndo[iPane];
  1052. glpobjUndo[iPane] = lpobjTemp;
  1053. ptyTemp = gpty[iPane];
  1054. gpty[iPane] = gptyUndo[iPane];
  1055. gptyUndo[iPane] = ptyTemp;
  1056. InvalidateRect(ghwndPane[iPane], NULL, TRUE);
  1057. Dirty();
  1058. }
  1059. static VOID
  1060. CalcWindows(
  1061. BOOL fFirst
  1062. )
  1063. {
  1064. if (fFirst)
  1065. {
  1066. // Figure out the length of the text strings, and all dimensions
  1067. HDC hdc = GetWindowDC(ghwndFrame);
  1068. if (hdc)
  1069. {
  1070. cxBorder = GetSystemMetrics(SM_CXBORDER);
  1071. cyBorder = GetSystemMetrics(SM_CYBORDER);
  1072. cxFudge = cxBorder * 2;
  1073. cyFudge = cyBorder * 2;
  1074. cxSplit = cxBorder * 4;
  1075. if (gbDBCS)
  1076. {
  1077. /* #3963 13-Dec-93 v-katsuy */
  1078. /* ORIGINALBUG! Window width calculated for just "&Picture".
  1079. * This width should be calculate
  1080. * [Radiobutton] + [Text](not include '&').
  1081. */
  1082. CHAR szTemp[CBMESSAGEMAX];
  1083. LPSTR lpText, lpTemp;
  1084. for (lpText = szPicture, lpTemp = szTemp; *lpText; ) {
  1085. if (*lpText == '&')
  1086. lpText++;
  1087. else
  1088. *lpTemp++ = *lpText++;
  1089. }
  1090. *lpTemp = 0;
  1091. cxPict = GetTextLen(hdc, szTemp) + cxFudge * 2
  1092. + GetSystemMetrics(SM_CXSIZE); // for radiobutton
  1093. for (lpText = szDescription, lpTemp = szTemp; *lpText; ) {
  1094. if (*lpText == '&')
  1095. lpText++;
  1096. else
  1097. *lpTemp++ = *lpText++;
  1098. }
  1099. *lpTemp = 0;
  1100. cxDesc = GetTextLen(hdc, szTemp)
  1101. + GetSystemMetrics(SM_CXSIZE); // for radiobutton
  1102. }
  1103. else
  1104. {
  1105. cxPict = GetTextLen(hdc, szPicture) + cxFudge * 2;
  1106. cxDesc = GetTextLen(hdc, szDescription);
  1107. }
  1108. cxView = GetTextLen(hdc, szView);
  1109. cxInsertIcon = GetTextLen(hdc, szInsertIcon) + cxFudge;
  1110. cxMin[CONTENT] = cxPict + cxDesc + cxView +
  1111. GetTextLen(hdc, gszCaption[CONTENT]) + cxFudge;
  1112. cxMin[APPEARANCE] = cxInsertIcon +
  1113. GetTextLen(hdc, gszCaption[APPEARANCE]) + cxFudge;
  1114. cyHeight = GetSystemMetrics(SM_CYMENU) + cyFudge * 2;
  1115. ReleaseDC(ghwndFrame, hdc);
  1116. cxMinWidth = cxMin[APPEARANCE] + cxMin[CONTENT] + cxSplit +
  1117. GetSystemMetrics(SM_CXFRAME) + cxFudge;
  1118. // Compute all the window sizes that we can
  1119. SetWindowPos(ghwndFrame, 0, 0, 0,
  1120. cxMinWidth + cxFudge * 20,
  1121. cxMinWidth * 7 / 18,
  1122. SWP_NOMOVE | SWP_NOZORDER);
  1123. SetWindowPos(hwndInsertIcon, 0, 0, 0,
  1124. cxInsertIcon - cxFudge,
  1125. GetSystemMetrics(SM_CYMENU),
  1126. SWP_NOMOVE | SWP_NOZORDER);
  1127. SetWindowPos(hwndView, 0, 0, 0,
  1128. cxView, cyHeight - cyFudge,
  1129. SWP_NOMOVE | SWP_NOZORDER);
  1130. SetWindowPos(ghwndPict, 0, 0, 0,
  1131. (cxPict - cxFudge) << 1,
  1132. GetSystemMetrics(SM_CYMENU),
  1133. SWP_NOMOVE | SWP_NOZORDER);
  1134. SetWindowPos(hwndDesc, 0, 0, 0,
  1135. cxDesc, GetSystemMetrics(SM_CYMENU),
  1136. SWP_NOMOVE | SWP_NOZORDER);
  1137. }
  1138. }
  1139. else
  1140. {
  1141. RECT rc;
  1142. GetClientRect(ghwndFrame, &rc);
  1143. // Move the windows to the appropriate locations
  1144. SetWindowPos(ghwndBar[APPEARANCE], 0, 0, 0,
  1145. xSplit - cxSplit / 2 - cxBorder, cyHeight, SWP_NOZORDER);
  1146. SetWindowPos(ghwndBar[CONTENT], 0,
  1147. xSplit + cxSplit / 2 + cxBorder,
  1148. 0,
  1149. rc.right - (xSplit + cxSplit / 2) + 1 - cxBorder,
  1150. cyHeight,
  1151. SWP_NOZORDER);
  1152. SetWindowPos(ghwndPane[APPEARANCE], 0,
  1153. -cxBorder,
  1154. cyHeight,
  1155. cxBorder + xSplit - cxSplit / 2,
  1156. rc.bottom + cyBorder - cyHeight,
  1157. SWP_NOZORDER);
  1158. SetWindowPos(ghwndPane[CONTENT], 0,
  1159. xSplit + cxSplit / 2,
  1160. cyHeight,
  1161. cxBorder + rc.right - (xSplit + cxSplit / 2) + 1,
  1162. rc.bottom + cyBorder - cyHeight,
  1163. SWP_NOZORDER);
  1164. }
  1165. }
  1166. static INT
  1167. Constrain(
  1168. INT x,
  1169. INT right
  1170. )
  1171. {
  1172. // Constrain the splitter bar...
  1173. if (x < cxMin[APPEARANCE] + cxSplit / 2 - 1)
  1174. return cxMin[APPEARANCE] + cxSplit / 2 - 1;
  1175. else if (x > (right - cxMin[CONTENT] - cxSplit / 2 + 1))
  1176. return right - cxMin[CONTENT] - cxSplit / 2 + 1;
  1177. return x;
  1178. }
  1179. /* CopyOther() - Copies the picture in appearance pane
  1180. *
  1181. * Returns: none
  1182. */
  1183. static VOID
  1184. CopyOther(
  1185. VOID
  1186. )
  1187. {
  1188. HANDLE hdata;
  1189. if (OpenClipboard(ghwndFrame))
  1190. {
  1191. Hourglass(TRUE);
  1192. EmptyClipboard();
  1193. if (hdata = GetMF())
  1194. SetClipboardData(CF_METAFILEPICT, hdata);
  1195. CloseClipboard();
  1196. Hourglass(FALSE);
  1197. }
  1198. }
  1199. VOID
  1200. DeletePaneObject(
  1201. LPVOID lpobj,
  1202. INT objType
  1203. )
  1204. {
  1205. switch (objType)
  1206. {
  1207. case CMDLINK:
  1208. CmlDelete(lpobj);
  1209. break;
  1210. case PEMBED:
  1211. EmbDelete(lpobj);
  1212. break;
  1213. case ICON:
  1214. IconDelete(lpobj);
  1215. break;
  1216. case PICTURE:
  1217. PicDelete(lpobj);
  1218. break;
  1219. }
  1220. }