|
|
1.1 root 1: // This is a part of the Microsoft Foundation Classes C++ library.
2: // Copyright (C) 1992 Microsoft Corporation
3: // All rights reserved.
4: //
5: // This source code is only intended as a supplement to the
6: // Microsoft Foundation Classes Reference and Microsoft
7: // QuickHelp documentation provided with the library.
8: // See these sources for detailed information regarding the
9: // Microsoft Foundation Classes product.
10:
11: #include "afxole.h"
12: #pragma hdrstop
13:
14: #include "afxoleUI.h" // user interface parts
15: #include "oleptr_.h"
16:
17: #include "shellapi.h"
18: #include "afxdlgs.h" // for Change link dialog
19:
20: #ifdef AFX_OLE_SEG
21: #pragma code_seg(AFX_OLE_SEG)
22: #endif
23:
24: #ifdef _DEBUG
25: #undef THIS_FILE
26: static char BASED_CODE THIS_FILE[] = __FILE__;
27: #endif
28:
29: /////////////////////////////////////////////////////////////////////////////
30: // User interface for COleClientItem (with Links)
31:
32: // forward references
33: static void FormatLinkInfo(COleClientItem* pItem, char* szInfoBuffer,
34: char* szClassNameBuffer);
35:
36: /////////////////////////////////////////////////////////////////////////////
37: // Links dialog
38:
39: class COleLinksDlg : public CModalDialog
40: {
41: public:
42: COleClientDoc* m_pDoc;
43: COleClientItem* m_pSingleSelection; // NULL if 0 or >1 items selected
44: int m_iSingleSelection; // listbox index (if above is not null)
45:
46: UINT m_iVerb1;
47: UINT m_iVerb2;
48:
49: // could be static members if desired
50: CString strEditVerb;
51: CString strActivateVerb;
52:
53: COleLinksDlg(COleClientDoc* pDoc)
54: : CModalDialog(AFX_IDD_LINKS)
55: {
56: m_pDoc = pDoc;
57: m_pSingleSelection = NULL;
58: VERIFY(strEditVerb.LoadString(AFX_IDS_EDIT_VERB));
59: VERIFY(strActivateVerb.LoadString(AFX_IDS_ACTIVATE_VERB));
60: }
61:
62: protected:
63: BOOL OnInitDialog();
64: void SetVerbButtons(COleClientItem* pSel);
65: void DoVerb(UINT iVerb);
66:
67: // message map notifications
68: afx_msg void OnSelectionChange();
69:
70: afx_msg void OnVerb1();
71: afx_msg void OnVerb2();
72: afx_msg void OnAuto();
73: afx_msg void OnManual();
74: afx_msg void OnUpdate();
75: afx_msg void OnFreeze();
76: afx_msg void OnChange();
77:
78: DECLARE_MESSAGE_MAP()
79: };
80:
81:
82: BEGIN_MESSAGE_MAP(COleLinksDlg, CModalDialog)
83: // selection change
84: ON_LBN_SELCHANGE(AFX_IDC_LISTBOX, OnSelectionChange)
85:
86: // control notifications
87: ON_COMMAND(AFX_IDC_VERB1, OnVerb1)
88: ON_COMMAND(AFX_IDC_VERB2, OnVerb2)
89: ON_COMMAND(AFX_IDC_AUTO, OnAuto)
90: ON_COMMAND(AFX_IDC_MANUAL, OnManual)
91: ON_COMMAND(AFX_IDC_UPDATE, OnUpdate)
92: ON_COMMAND(AFX_IDC_FREEZE, OnFreeze)
93: ON_COMMAND(AFX_IDC_CHANGE, OnChange)
94: END_MESSAGE_MAP()
95:
96: /////////////////////////////////////////////////////////////////////////////
97: // Initialize - fill in the information
98:
99: BOOL COleLinksDlg::OnInitDialog()
100: {
101: CListBox* pList = (CListBox*)GetDlgItem(AFX_IDC_LISTBOX);
102: int cLinks = 0;
103:
104: // fill with links attached to this object
105: pList->ResetContent();
106:
107: int tabStops[3];
108: tabStops[0] = 20; // 20 50
109: tabStops[1] = 80; // 60 110
110: tabStops[2] = 120; // 85 200
111: pList->SetTabStops(3, tabStops);
112:
113: // enumerate over the client document - enumerate OLEOBJECTs
114: BOOL bSelected;
115: POSITION pos = m_pDoc->GetStartPosition();
116: COleClientItem* pItem;
117:
118: while ((pItem = m_pDoc->GetNextItem(pos, &bSelected)) != NULL)
119: {
120: if (pItem->GetType() == OT_LINK)
121: {
122: // add it to the listbox
123: int iItem;
124: char szInfo[OLE_MAXNAMESIZE * 2]; // assume this is enough
125:
126: FormatLinkInfo(pItem, szInfo, NULL);
127: if ((iItem = pList->AddString(szInfo)) == -1)
128: {
129: TRACE("Warning: error filling listbox\n");
130: EndDialog(IDCANCEL);
131: return TRUE;
132: }
133:
134: pList->SetItemData(iItem, GetDWordFromPtr(pItem));
135: if (bSelected)
136: pList->SetSel(iItem);
137: cLinks++;
138: }
139: }
140:
141: if (cLinks == 0)
142: {
143: TRACE("Warning: no links in this document\n");
144: EndDialog(IDCANCEL); // no links after all
145: return TRUE;
146: }
147:
148: OnSelectionChange(); // enables buttons etc
149: return TRUE;
150: }
151:
152: struct LinkOptionsInfo
153: {
154: int nIDString; // IDS_ value to LoadString
155: int nIDCheckButton; // IDC_ for button to check
156: BOOL bCanChangeLink; // if can change or freeze
157: };
158:
159: static void GetLinkUpdateInfo(COleClientItem* pItem, LinkOptionsInfo* pInfo)
160: {
161: // sensible defaults
162: pInfo->nIDString = AFX_IDS_FROZEN;
163: pInfo->nIDCheckButton = -1;
164: pInfo->bCanChangeLink = FALSE;
165:
166: if (pItem->GetType() != OT_LINK)
167: return; // assume static
168:
169: switch (pItem->GetLinkUpdateOptions())
170: {
171: case oleupdate_always:
172: pInfo->nIDString = AFX_IDS_AUTO;
173: pInfo->nIDCheckButton = AFX_IDC_AUTO;
174: pInfo->bCanChangeLink = TRUE;
175: break;
176:
177: case oleupdate_oncall:
178: pInfo->nIDString = AFX_IDS_MANUAL;
179: pInfo->nIDCheckButton = AFX_IDC_MANUAL;
180: pInfo->bCanChangeLink = TRUE;
181: break;
182:
183: default:
184: break; // default already setup (static)
185: }
186: }
187:
188:
189: static void FormatLinkInfo(COleClientItem* pItem, char* szInfoBuffer,
190: char* szClassNameBuffer)
191: {
192: struct LinkOptionsInfo linkInfo;
193: CString strLinkType;
194:
195: GetLinkUpdateInfo(pItem, &linkInfo);
196: VERIFY(strLinkType.LoadString(linkInfo.nIDString));
197:
198: HANDLE hData = pItem->GetLinkFormatData();
199: ASSERT(hData != NULL);
200: LPCSTR lpszData = (LPCSTR)::GlobalLock(hData); // actually 3 strings
201: ASSERT(lpszData != NULL);
202:
203: if (szClassNameBuffer != NULL)
204: _fstrcpy(szClassNameBuffer, lpszData);
205:
206: if (szInfoBuffer != NULL)
207: {
208: // first server class name (use localized name if registered)
209: LONG lSize = OLE_MAXNAMESIZE;
210: // get real language class of object in szClass for menu
211: if (::RegQueryValue(HKEY_CLASSES_ROOT, lpszData, szInfoBuffer,
212: &lSize) != ERROR_SUCCESS)
213: {
214: // no localized class name, use unlocalized name
215: _fstrcpy(szInfoBuffer, lpszData);
216: }
217: _fstrcat(szInfoBuffer, "\t");
218:
219: // document and item names
220: lpszData += _fstrlen(lpszData) + 1;
221:
222: // strip pathname and drive letter
223: LPCSTR lpszTemp = lpszData;
224: while (*lpszTemp)
225: {
226: if (*lpszTemp == '\\' || *lpszTemp == ':')
227: lpszData = lpszTemp + 1;
228: lpszTemp = AnsiNext(lpszTemp);
229: }
230:
231: // Append the file name
232: _fstrcat(szInfoBuffer, lpszData);
233: _fstrcat(szInfoBuffer, "\t");
234:
235: // Append the item name
236: lpszData += _fstrlen(lpszData) + 1;
237: _fstrcat(szInfoBuffer, lpszData);
238: _fstrcat(szInfoBuffer, "\t");
239:
240: /* Append the type of link, and write it out */
241: _fstrcat(szInfoBuffer, strLinkType);
242: }
243:
244: ::GlobalUnlock(hData);
245: }
246:
247: // update button states depending on current selection
248: void COleLinksDlg::OnSelectionChange()
249: {
250: CListBox* pList = (CListBox*)GetDlgItem(AFX_IDC_LISTBOX);
251: int nSelectedLinks = 0;
252: int nIDCheck = -1;
253: BOOL bCanChangeLink = FALSE;
254:
255: m_pSingleSelection = NULL;
256:
257: ASSERT(AFX_IDC_MANUAL == AFX_IDC_AUTO + 1);
258: if (pList->GetSelCount() != 0)
259: {
260: int nTotal = pList->GetCount();
261: for (int iItem = 0; iItem < nTotal; iItem++)
262: {
263: if (pList->GetSel(iItem) <= 0)
264: continue; // not selected
265:
266: COleClientItem* pItem;
267: pItem = (COleClientItem*)GetPtrFromDWord(pList->GetItemData(iItem));
268: ASSERT(pItem != NULL);
269: struct LinkOptionsInfo linkInfo;
270:
271: GetLinkUpdateInfo(pItem, &linkInfo);
272:
273: if (nSelectedLinks++ == 0)
274: {
275: // first link
276: nIDCheck = linkInfo.nIDCheckButton;
277: bCanChangeLink = linkInfo.bCanChangeLink;
278: m_pSingleSelection = pItem;
279: m_iSingleSelection = iItem;
280: }
281: else
282: {
283: if (nIDCheck != linkInfo.nIDCheckButton) // not the same
284: nIDCheck = -1;
285:
286: // if multiple links selected - don't allow anything complex
287: if (!linkInfo.bCanChangeLink)
288: bCanChangeLink = FALSE;
289: m_pSingleSelection = NULL;
290: }
291: }
292: }
293:
294: //BLOCK: do pushbutton verb stuff
295: SetVerbButtons(m_pSingleSelection);
296:
297: // disable if all in selection can be changed
298: GetDlgItem(AFX_IDC_UPDATE)->EnableWindow(bCanChangeLink);
299: GetDlgItem(AFX_IDC_FREEZE)->EnableWindow(bCanChangeLink);
300:
301: // simple Change button - only one link at a time
302: GetDlgItem(AFX_IDC_CHANGE)->EnableWindow(
303: (m_pSingleSelection != NULL) && bCanChangeLink);
304:
305:
306: CheckRadioButton(AFX_IDC_AUTO, AFX_IDC_MANUAL, nIDCheck);
307: // disable if nothing selected
308: GetDlgItem(AFX_IDC_AUTO)->EnableWindow(nSelectedLinks > 0);
309: GetDlgItem(AFX_IDC_MANUAL)->EnableWindow(nSelectedLinks > 0);
310: }
311:
312: /////////////////////////////////////////////////////////////////////////////
313: // Standard verb buttons
314:
315: static void SmartChangeButton(CWnd* pButton, const char* pszText, BOOL bEnable)
316: {
317: char szOldText[OLE_MAXNAMESIZE];
318:
319: // avoid flashing if changing to same text
320: pButton->GetWindowText(szOldText, sizeof(szOldText));
321: if (strcmp(szOldText, pszText) != 0)
322: pButton->SetWindowText(pszText);
323: pButton->EnableWindow(bEnable);
324: }
325:
326: void COleLinksDlg::SetVerbButtons(COleClientItem* pSel)
327: {
328: // defaults for no selection
329: const char* pszVerb1 = strActivateVerb;
330: BOOL bEnable1 = FALSE;
331: const char* pszVerb2 = strEditVerb;
332: BOOL bEnable2 = FALSE;
333:
334: // registered verb names
335: char szRegVerb0[OLE_MAXNAMESIZE];
336: char szRegVerb1[OLE_MAXNAMESIZE];
337:
338: ASSERT(OLEVERB_PRIMARY == 0);
339: m_iVerb1 = m_iVerb2 = 0; // usually primary verb
340:
341: if (pSel != NULL)
342: {
343: // look at verbs for current selection
344: char szClass[OLE_MAXNAMESIZE];
345: FormatLinkInfo(pSel, NULL, szClass);
346:
347: szRegVerb0[0] = szRegVerb1[0] = '\0';
348: int cVerbs = 0;
349: while (cVerbs < 2)
350: {
351: char szBuffer[OLE_MAXNAMESIZE+40];
352: wsprintf(szBuffer, "%s\\protocol\\StdFileEditing\\verb\\%d",
353: (LPCSTR)szClass, cVerbs);
354:
355: /* get verb name */
356: char* pszVerb = (cVerbs == 0) ? szRegVerb0 : szRegVerb1;
357: LONG lSize = OLE_MAXNAMESIZE;
358: if (::RegQueryValue(HKEY_CLASSES_ROOT, szBuffer,
359: pszVerb, &lSize) != 0)
360: break; // finished counting verbs
361: cVerbs++;
362: }
363:
364: if (cVerbs == 0)
365: {
366: // no special verbs, enable generic edit
367: bEnable2 = TRUE;
368: }
369: else if (cVerbs == 1)
370: {
371: // 1 special verb, special case if 'edit'
372: if (_stricmp(szRegVerb0, strEditVerb) == 0)
373: {
374: // edit goes on second button
375: bEnable2 = TRUE;
376: }
377: else
378: {
379: // other verb goes on top
380: pszVerb1 = szRegVerb0;
381: bEnable1 = TRUE;
382: }
383: }
384: else // 2 verbs
385: {
386: bEnable1 = bEnable2 = TRUE;
387: if (_stricmp(szRegVerb0, strEditVerb) == 0)
388: {
389: pszVerb1 = szRegVerb1;
390: m_iVerb1 = 1;
391: // verb 2 is already edit
392: }
393: else if (_stricmp(szRegVerb1, strEditVerb) == 0)
394: {
395: pszVerb1 = szRegVerb0;
396: // verb 2 is already edit
397: }
398: else
399: {
400: pszVerb1 = szRegVerb0;
401: pszVerb2 = szRegVerb1;
402: m_iVerb2 = 1;
403: }
404: }
405: }
406:
407: SmartChangeButton(GetDlgItem(AFX_IDC_VERB1), pszVerb1, bEnable1);
408: SmartChangeButton(GetDlgItem(AFX_IDC_VERB2), pszVerb2, bEnable2);
409: }
410:
411: /////////////////////////////////////////////////////////////////////////////
412:
413: void COleLinksDlg::DoVerb(UINT iVerb)
414: {
415: ASSERT(m_pSingleSelection != NULL);
416:
417: if (afxTraceFlags & 0x10)
418: TRACE("Executing verb %d on server\n", iVerb);
419:
420: TRY
421: m_pSingleSelection->Activate(iVerb);
422: CATCH (COleException, e)
423: m_pSingleSelection->ReportError(e->m_status);
424: END_CATCH
425:
426: // End the dialog after launch
427: EndDialog(IDOK);
428: }
429:
430: void COleLinksDlg::OnVerb1()
431: {
432: DoVerb(m_iVerb1);
433: }
434:
435: void COleLinksDlg::OnVerb2()
436: {
437: DoVerb(m_iVerb2);
438: }
439:
440: #define FOR_EACH_SELECTED_ITEM(pItem) \
441: CListBox* _pList = (CListBox*)GetDlgItem(AFX_IDC_LISTBOX); \
442: int _nTotal = _pList->GetCount(); \
443: for (int _iItem = 0; _iItem < _nTotal; _iItem++) \
444: { \
445: if (_pList->GetSel(_iItem) <= 0) \
446: continue; /* not selected */ \
447: COleClientItem* pItem; \
448: pItem = (COleClientItem*)GetPtrFromDWord(_pList->GetItemData(_iItem));\
449: ASSERT(pItem != NULL);
450:
451: #define UPDATE_SELECTED(pItem) \
452: UpdateSelectedItem(_pList, pItem, _iItem)
453:
454: #define DELETE_SELECTED() \
455: _pList->DeleteString(_iItem); \
456: _iItem--; /* for next in the loop */ \
457: _nTotal--; /* for next in the loop */
458:
459: #define END_EACH_SELECTED_ITEM() \
460: }
461:
462:
463: static void UpdateSelectedItem(CListBox* pList,
464: COleClientItem* pItem, int iItem)
465: {
466: char szInfo[OLE_MAXNAMESIZE * 2];
467: FormatLinkInfo(pItem, szInfo, NULL);
468: pList->DeleteString(iItem);
469: pList->InsertString(iItem, szInfo);
470: pList->SetItemData(iItem, GetDWordFromPtr(pItem));
471: pList->SetSel(iItem);
472: }
473:
474:
475: void COleLinksDlg::OnAuto()
476: {
477: FOR_EACH_SELECTED_ITEM(pItem)
478: {
479: pItem->SetLinkUpdateOptions(oleupdate_always);
480: UPDATE_SELECTED(pItem);
481: }
482: END_EACH_SELECTED_ITEM()
483: }
484:
485: void COleLinksDlg::OnManual()
486: {
487: FOR_EACH_SELECTED_ITEM(pItem)
488: {
489: pItem->SetLinkUpdateOptions(oleupdate_oncall);
490: UPDATE_SELECTED(pItem);
491: }
492: END_EACH_SELECTED_ITEM()
493: }
494:
495: void COleLinksDlg::OnUpdate()
496: {
497: FOR_EACH_SELECTED_ITEM(pItem)
498: {
499: TRY
500: pItem->UpdateLink();
501: CATCH (COleException, e)
502: pItem->ReportError(e->m_status);
503: END_CATCH
504: }
505: END_EACH_SELECTED_ITEM()
506: }
507:
508: void COleLinksDlg::OnFreeze()
509: {
510: FOR_EACH_SELECTED_ITEM(pItem)
511: {
512: TRY
513: {
514: if (pItem->FreezeLink(pItem->GetName()))
515: {
516: DELETE_SELECTED();
517: }
518: else
519: {
520: pItem->ReportError(OLE_ERROR_COMM); // strange error
521: }
522: }
523: CATCH (COleException, e)
524: {
525: pItem->ReportError(OLE_ERROR_COMM); // strange error
526: }
527: END_CATCH
528: }
529: END_EACH_SELECTED_ITEM()
530:
531: if (_pList->GetCount() == 0)
532: EndDialog(IDOK);
533: }
534:
535: void COleLinksDlg::OnChange()
536: {
537: // We only support changing of one item at a time
538: // The full UISG UI includes more complicated functionality
539: COleClientItem* pItem = m_pSingleSelection;
540: ASSERT(pItem != NULL);
541: ASSERT(pItem->GetType() == OT_LINK);
542:
543: HANDLE hData = pItem->GetLinkFormatData();
544: ASSERT(hData != NULL);
545: LPCSTR lpszData = (LPCSTR)::GlobalLock(hData);
546: ASSERT(lpszData != NULL);
547:
548: UINT cbClassName = _fstrlen(lpszData);
549: LPCSTR lpszDoc = lpszData + cbClassName + 1;
550: LPCSTR lpszItems = lpszDoc + _fstrlen(lpszDoc) + 1;
551:
552: char szPath[_MAX_PATH];
553: _fstrcpy(szPath, lpszDoc);
554:
555:
556:
557: CString title;
558: CString filter;
559: CFileDialog dlgFile(TRUE, NULL, szPath,
560: OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR,
561: (filter.LoadString(AFX_IDS_ALL_FILES) ? (LPCSTR)filter : NULL),
562: this);
563:
564: if (title.LoadString(AFX_IDS_CHANGE_LINK))
565: dlgFile.m_ofn.lpstrTitle = title;
566:
567: dlgFile.m_ofn.lpstrFile = (LPSTR)szPath; // just fill in my own buffer
568:
569: if (dlgFile.DoModal() == IDCANCEL)
570: return;
571:
572:
573: // change the path name
574: HANDLE hNewData = ::GlobalAlloc(GMEM_DDESHARE | GMEM_ZEROINIT,
575: cbClassName + 1 + _fstrlen(szPath) + 1 + _fstrlen(lpszItems) + 1 + 1);
576: if (hNewData == NULL)
577: {
578: pItem->ReportError(OLE_ERROR_MEMORY);
579: return;
580: }
581: LPSTR lpszNew = (LPSTR)::GlobalLock(hNewData);
582: ASSERT(lpszNew != NULL);
583:
584: // copy the old class name, new doc name and old item names
585: _fstrcpy(lpszNew, lpszData);
586: lpszNew += cbClassName + 1;
587: _fstrcpy(lpszNew, szPath);
588: lpszNew += _fstrlen(lpszNew) + 1;
589: _fstrcpy(lpszNew, lpszItems);
590: lpszNew += _fstrlen(lpszNew) + 1;
591: *lpszNew = '\0'; // terminate it
592:
593: pItem->SetData((OLECLIPFORMAT)::RegisterClipboardFormat("ObjectLink"),
594: hNewData);
595: // update the selection in the listbox
596: UpdateSelectedItem((CListBox*)GetDlgItem(AFX_IDC_LISTBOX),
597: m_pSingleSelection, m_iSingleSelection);
598: }
599:
600:
601: /////////////////////////////////////////////////////////////////////////////
602: // Public interface for running modal dialog
603:
604: BOOL AfxOleLinksDialog(COleClientDoc* pDoc)
605: {
606: COleLinksDlg dlg(pDoc);
607:
608: return (dlg.DoModal() == IDOK);
609: }
610:
611: /////////////////////////////////////////////////////////////////////////////
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.