• R/O
  • HTTP
  • SSH
  • HTTPS

SeraphyScriptTools: Commit

SeraphyScriptTools v1.1以降のソースコード管理


Commit MetaInfo

Revisionfa17d5607643409fcab4bad0136fab468e89fb43 (tree)
Time2015-08-18 03:34:02
Authorseraphy <seraphy@sera...>
Commiterseraphy

Log Message

フォルダ選択ダイアログのヒープエラーの修正、参照カウントの確認

Change Summary

Incremental Difference

--- a/CComEnumDynaVARIANT.h
+++ b/CComEnumDynaVARIANT.h
@@ -8,7 +8,7 @@ typedef CComEnum<IEnumVARIANT, &IID_IEnumVARIANT, VARIANT, _Copy<VARIANT> > CCom
88
99 // 動的なバリアント列挙型
1010 template <class T>
11-class CComEnumDynaVARIANT :public IEnumVARIANT, public CComObjectRootEx<CComSingleThreadModel>
11+class CComEnumDynaVARIANT :public IEnumVARIANT, public CComObjectRootEx < CComSingleThreadModel >
1212 {
1313 public:
1414 BEGIN_COM_MAP(CComEnumDynaVARIANT)
@@ -100,9 +100,11 @@ STDMETHODIMP CComEnumDynaVARIANT<T>::Reset()
100100 template<class T>
101101 STDMETHODIMP CComEnumDynaVARIANT<T>::Clone(IEnumVARIANT FAR* FAR* ppenum)
102102 {
103- CComObject< CComEnumDynaVARIANT<T> >* pClone = NULL;
104- pClone->CreateInstance(&pClone);
103+ CComObject<CComEnumDynaVARIANT<T>>* pClone = NULL;
104+ HRESULT hr;
105+ if (FAILED(hr = CComObject<CComEnumDynaVARIANT<T>>::CreateInstance(&pClone))) {
106+ return hr;
107+ }
105108 pClone->Init(m_pObj, m_current);
106- pClone->QueryInterface(IID_IEnumVARIANT, (void**)ppenum);
107- return S_OK;
109+ return pClone->QueryInterface(IID_IEnumVARIANT, (void**)ppenum);
108110 }
--- a/CommDialog.cpp
+++ b/CommDialog.cpp
@@ -72,7 +72,7 @@ void CCommDialog::CommFileDialog(VARIANT *pvarReturn, VARIANT varPathName, VARIA
7272 const int MAXBUFSIZ = MAX_PATH * 10;
7373 LPTSTR pStrFileBuf = strFile.GetBufferSetLength(MAXBUFSIZ + 1);
7474
75- OPENFILENAME ofn = {0};
75+ OPENFILENAME ofn = { 0 };
7676 ofn.lStructSize = sizeof(OPENFILENAME);
7777 ofn.lpstrFilter = szFilter;
7878 ofn.lpstrFile = pStrFileBuf;
@@ -326,14 +326,10 @@ STDMETHODIMP CCommDialog::BrowseForFolder(VARIANT varCaption, VARIANT varDir, VA
326326 put_BrowseForFolderCaption(caption.bstrVal);
327327 }
328328
329- BROWSEINFO binfo = {0};
330- binfo.hwndOwner = GetMainWindow();
331-
332329 ATL::CString szTitle;
333330 {
334331 if (m_bstr_BrowseForFolderCaption.length() > 0) {
335332 szTitle = (LPCWSTR)m_bstr_BrowseForFolderCaption;
336- binfo.lpszTitle = szTitle;
337333 }
338334 }
339335
@@ -344,9 +340,18 @@ STDMETHODIMP CCommDialog::BrowseForFolder(VARIANT varCaption, VARIANT varDir, VA
344340 // ファイル名の取り出し
345341 szDirName = path.bstrVal;
346342 }
347- binfo.pszDisplayName = szDirName.GetBuffer();
348343 }
349344
345+ CComBSTR strInitDir(szDirName);
346+
347+ BROWSEINFO binfo = { 0 };
348+ binfo.hwndOwner = GetMainWindow();
349+ binfo.pidlRoot = NULL;
350+ binfo.lpszTitle = szTitle.IsEmpty() ? NULL : szTitle;
351+ binfo.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE | BIF_SHAREABLE;
352+ // 必ずMAX_PATHのバッファを確保する
353+ binfo.pszDisplayName = szDirName.GetBufferSetLength(MAX_PATH);
354+
350355 int mode = 0;
351356 CComVariant varTmp;
352357 if (SUCCEEDED(varTmp.ChangeType(VT_I4, &varMode))) {
@@ -355,22 +360,23 @@ STDMETHODIMP CCommDialog::BrowseForFolder(VARIANT varCaption, VARIANT varDir, VA
355360
356361 binfo.ulFlags = 0;//BIF_NEWDIALOGSTYLE; // BIF_USENEWUI
357362 switch (mode & 0x0f) {
358- case 0:
359- default:
363+ case 0:
364+ default:
360365 binfo.ulFlags |= BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;
361366 binfo.lpfn = BrowseCallbackProc;
362- binfo.lParam = (LPARAM)(LPCTSTR)szDirName;
367+ // BFFM_SETSELECTIONで初期フォルダを指定する場合、パラメータは常にUNICODEである.
368+ binfo.lParam = reinterpret_cast<LPARAM>(static_cast<LPCWSTR>(strInitDir));
363369 break;
364370
365- case 1:
371+ case 1:
366372 binfo.ulFlags |= BIF_BROWSEFORCOMPUTER;
367373 break;
368374
369- case 2:
375+ case 2:
370376 binfo.ulFlags |= BIF_BROWSEFORPRINTER;
371377 break;
372378
373- case 3:
379+ case 3:
374380 binfo.ulFlags |= BIF_RETURNFSANCESTORS;
375381 break;
376382 }
@@ -385,22 +391,26 @@ STDMETHODIMP CCommDialog::BrowseForFolder(VARIANT varCaption, VARIANT varDir, VA
385391 binfo.ulFlags |= BIF_DONTGOBELOWDOMAIN;
386392 }
387393
394+ // シェルのアロケータ
395+ CComPtr<IMalloc> pMalloc(NULL);
396+ HRESULT hr;
397+ if (FAILED(hr = SHGetMalloc(&pMalloc))) {
398+ return hr;
399+ }
400+
401+ // フォルダのブラウズ
388402 LPITEMIDLIST idlst = NULL;
389403 if ((idlst = SHBrowseForFolder(&binfo)) != NULL) {
390- IMalloc *pMalloc = NULL;
391- HRESULT hr = SHGetMalloc(&pMalloc);
392- if (FAILED(hr)) {
393- return hr;
394- }
395404
405+ // 結果パスの取得
406+ CComVariant tmp(_TEXT("")); // 取得できない場合は空文字
396407 ATL::CString ret;
397- LPTSTR pRet = ret.GetBufferSetLength(MAX_PATH);
398- SHGetPathFromIDList(idlst, pRet);
408+ TCHAR path[MAX_PATH] = { 0 };
409+ if (SHGetPathFromIDList(idlst, path)) {
410+ tmp = path;
411+ }
399412
400413 pMalloc->Free(idlst);
401- pMalloc->Release();
402-
403- CComVariant tmp(pRet);
404414 return tmp.Detach(pvarReturn);
405415 }
406416 return S_OK;
@@ -410,17 +420,27 @@ STDMETHODIMP CCommDialog::BrowseForFolder(VARIANT varCaption, VARIANT varDir, VA
410420 int CALLBACK CCommDialog::BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
411421 {
412422 switch (uMsg) {
413- case BFFM_INITIALIZED:
414- SendMessage(hwnd, BFFM_SETSELECTION, true, lpData);
423+ case BFFM_INITIALIZED:
424+ if (lpData) {
425+ SendMessage(hwnd, BFFM_SETSELECTION, true, lpData);
426+ }
415427 break;
416- case BFFM_SELCHANGED:
428+
429+ case BFFM_SELCHANGED:
417430 {
418- TCHAR szBuf[MAX_PATH];
419- BOOL bResult = SHGetPathFromIDList((LPITEMIDLIST)lParam, szBuf);
420- SendMessage(hwnd, BFFM_ENABLEOK, 0, bResult);
431+ LPITEMIDLIST pidl = reinterpret_cast<LPITEMIDLIST>(lParam);
432+ BOOL enabled = FALSE;
433+ if (pidl) {
434+ TCHAR tmp[MAX_PATH];
435+ if (SHGetPathFromIDList(pidl, tmp)) {
436+ enabled = TRUE;
437+ }
438+ }
439+ SendMessage(hwnd, BFFM_ENABLEOK, 0, enabled);
421440 }
422441 break;
423- case BFFM_VALIDATEFAILED:
442+
443+ case BFFM_VALIDATEFAILED:
424444 break;
425445 }
426446 return 0;
@@ -444,10 +464,11 @@ STDMETHODIMP CCommDialog::SetMainWindow(VARIANT varUnk)
444464 }
445465 // インターフェイスの取得
446466 CComVariant tmp;
447- if (SUCCEEDED(tmp.ChangeType(VT_UNKNOWN, &varUnk))) {
448- return tmp.punkVal->QueryInterface(IID_IOverlappedWindow, (void**)&m_pMainWindow);
467+ HRESULT hr;
468+ if (FAILED(hr = tmp.ChangeType(VT_UNKNOWN, &varUnk))) {
469+ return hr;
449470 }
450- return DISP_E_UNKNOWNINTERFACE;
471+ return tmp.punkVal->QueryInterface(&m_pMainWindow);
451472 }
452473
453474 STDMETHODIMP CCommDialog::MessageBox(VARIANT mes, VARIANT typ, VARIANT icon, VARIANT* pRet)
@@ -468,28 +489,28 @@ STDMETHODIMP CCommDialog::MessageBox(VARIANT mes, VARIANT typ, VARIANT icon, VAR
468489 }
469490
470491 switch (varType.iVal % 10) {
471- case 0:
472- default:
492+ case 0:
493+ default:
473494 mode |= MB_OK;
474495 break;
475496
476- case 1:
497+ case 1:
477498 mode |= MB_OKCANCEL;
478499 break;
479500
480- case 2:
501+ case 2:
481502 mode |= MB_YESNO;
482503 break;
483504
484- case 3:
505+ case 3:
485506 mode |= MB_YESNOCANCEL;
486507 break;
487508
488- case 4:
509+ case 4:
489510 mode |= MB_RETRYCANCEL;
490511 break;
491512
492- case 5:
513+ case 5:
493514 mode |= MB_ABORTRETRYIGNORE;
494515 break;
495516 }
@@ -497,23 +518,23 @@ STDMETHODIMP CCommDialog::MessageBox(VARIANT mes, VARIANT typ, VARIANT icon, VAR
497518
498519 if (SUCCEEDED(varIcon.ChangeType(VT_I2, &icon))) {
499520 switch (varIcon.iVal) {
500- case 0:
501- default:
521+ case 0:
522+ default:
502523 break;
503524
504- case 1:
525+ case 1:
505526 mode |= MB_ICONERROR;
506527 break;
507528
508- case 2:
529+ case 2:
509530 mode |= MB_ICONWARNING;
510531 break;
511532
512- case 3:
533+ case 3:
513534 mode |= MB_ICONINFORMATION;
514535 break;
515536
516- case 4:
537+ case 4:
517538 mode |= MB_ICONQUESTION;
518539 break;
519540 }
@@ -521,17 +542,17 @@ STDMETHODIMP CCommDialog::MessageBox(VARIANT mes, VARIANT typ, VARIANT icon, VAR
521542
522543 int md = ::MessageBox(GetMainWindow(), msg, GetMainCaption(), mode);
523544 switch (md) {
524- case IDOK:
525- case IDYES:
526- case IDRETRY:
545+ case IDOK:
546+ case IDYES:
547+ case IDRETRY:
527548 ret = (short)1;
528549 break;
529- case IDCANCEL:
530- case IDABORT:
550+ case IDCANCEL:
551+ case IDABORT:
531552 ret = (short)-1;
532553 break;
533- case IDNO:
534- case IDIGNORE:
554+ case IDNO:
555+ case IDIGNORE:
535556 ret = (short)0;
536557 break;
537558 }
--- a/Control.cpp
+++ b/Control.cpp
@@ -8,11 +8,8 @@
88 #include "objectmap.h"
99 #include "CComEnumDynaVARIANT.h"
1010
11-#include <list>
1211 #include <vector>
1312
14-using namespace std;
15-
1613 /////////////////////////////////////////////////////////////////////////////
1714 // CControl
1815
@@ -492,17 +489,21 @@ STDMETHODIMP CControl::AddString(VARIANT text, VARIANT* pRet)
492489 ret = (short)SendMessage(m_hWnd, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)buf);
493490 }
494491 else if (!lstrcmp(m_classname, _TEXT("LISTBOX"))) {
492+ // 連想配列オブジェクトを作成する
493+ CComObject<CObjectMap>* pMap = NULL;
494+ if (FAILED(hr = CComObject<CObjectMap>::CreateInstance(&pMap))) {
495+ return hr;
496+ }
497+ IUnknown* pMapUnk = NULL;
498+ if (FAILED(hr = pMap->QueryInterface(&pMapUnk))) {
499+ return hr;
500+ }
501+
495502 // リストボックスに文字列を追加する
496503 int nIdx = SendMessage(m_hWnd, LB_ADDSTRING, 0, (LPARAM)(LPCTSTR)buf);
497504
498- // 連想配列オブジェクトをバインドする
499- CComObject<CObjectMap>* pMap = NULL;
500- if (SUCCEEDED(CComObject<CObjectMap>::CreateInstance(&pMap))) {
501- IUnknown* pUnk = NULL;
502- if (SUCCEEDED(pMap->QueryInterface(IID_IUnknown, (void**)&pUnk))) {
503- ::SendMessage(m_hWnd, LB_SETITEMDATA, nIdx, (LPARAM)pUnk);
504- }
505- }
505+ // リストボックスのアイテムに連想配列をバインドする.
506+ ::SendMessage(m_hWnd, LB_SETITEMDATA, nIdx, (LPARAM)pMapUnk);
506507 ret = (short)nIdx;
507508 }
508509 else if (!lstrcmp(m_classname, WC_LISTVIEW)) {
@@ -521,11 +522,16 @@ STDMETHODIMP CControl::AddString(VARIANT text, VARIANT* pRet)
521522
522523 // 連想配列オブジェクトをバインドする
523524 CComObject<CObjectMap>* pMap = NULL;
525+ if (FAILED(hr = CComObject<CObjectMap>::CreateInstance(&pMap))) {
526+ return hr;
527+ }
528+
524529 IUnknown* pUnk = NULL;
525- if (SUCCEEDED(pMap->CreateInstance(&pMap))) {
526- pMap->QueryInterface(IID_IUnknown, (void**)&pUnk);
530+ if (FAILED(hr = pMap->QueryInterface(IID_IUnknown, (void**)&pUnk))) {
531+ return hr;
527532 }
528- LVITEM itm = {0};
533+
534+ LVITEM itm = { 0 };
529535 itm.iItem = nIdx;
530536 itm.mask = LVIF_PARAM;
531537 itm.lParam = (LPARAM)pUnk;
@@ -534,10 +540,13 @@ STDMETHODIMP CControl::AddString(VARIANT text, VARIANT* pRet)
534540 }
535541 else if (!lstrcmp(m_classname, WC_TREEVIEW)) {
536542 // ツリービューのルートにアイテムを作成する
537- IUnknown* pUnk = NULL;
538- CTreeItem::CreateTreeItem(m_hWnd, TVI_ROOT, buf, &pUnk);
543+ CComPtr<IUnknown> pUnk;
544+ HRESULT hr;
545+ if (FAILED(hr = CTreeItem::CreateTreeItem(m_hWnd, TVI_ROOT, buf, &pUnk))) {
546+ return hr;
547+ }
539548 if (pUnk != NULL) {
540- ret = (IUnknown*)pUnk;
549+ ret = pUnk; // pUnkはVariant代入時にAddRefされるのでDetachは不要.
541550 }
542551 }
543552 else {
@@ -683,9 +692,8 @@ STDMETHODIMP CControl::get_ItemObject(VARIANT idx, VARIANT *pVal)
683692 }
684693
685694 if (pUnk) {
686- pUnk->AddRef();
687- pVal->vt = VT_UNKNOWN;
688- pVal->punkVal = pUnk;
695+ CComVariant tmp(pUnk);
696+ return tmp.Detach(pVal);
689697 }
690698 return S_OK;
691699 }
@@ -895,14 +903,20 @@ STDMETHODIMP CControl::get_CurrentSelectedItem(VARIANT *pVal)
895903 HTREEITEM hItem = TreeView_GetSelection(m_hWnd);
896904 if (hItem) {
897905 CComObject<CTreeItem>* pItem = NULL;
898- if (SUCCEEDED(pItem->CreateInstance(&pItem))) {
899- pItem->AddRef();
900- pItem->SetParam(m_hWnd, hItem);
901- IUnknown* pUnk = NULL;
902- if (SUCCEEDED(pItem->QueryInterface(IID_IUnknown, (void**)&pUnk))) {
903- ret = pUnk;
904- }
906+ HRESULT hr;
907+ if (FAILED(hr = CComObject<CTreeItem>::CreateInstance(&pItem))) {
908+ return hr;
905909 }
910+
911+ IUnknown* pUnk = NULL;
912+ if (FAILED(hr = pItem->QueryInterface(&pUnk))) {
913+ delete pItem;
914+ return hr;
915+ }
916+
917+ //FIXME: 不要のはず pItem->AddRef();
918+ pItem->SetParam(m_hWnd, hItem);
919+ ret = pUnk;
906920 }
907921 }
908922 else {
@@ -1029,12 +1043,13 @@ STDMETHODIMP CControl::get__NewEnum(IUnknown **pVal)
10291043
10301044 // 列挙インターフェイスの生成
10311045 CComObject<CComEnumVARIANT>* pCol = NULL;
1032- if (SUCCEEDED(CComObject<CComEnumVARIANT>::CreateInstance(&pCol))) {
1033- pCol->AddRef();
1034- pCol->Init(&varArray[0], &varArray[mx], pCol, AtlFlagCopy);
1035- *pVal = pCol;
1046+ HRESULT hr;
1047+ if (FAILED(hr = CComObject<CComEnumVARIANT>::CreateInstance(&pCol))) {
1048+ return hr;
10361049 }
1037- return S_OK;
1050+ pCol->Init(&varArray[0], &varArray[mx], pCol, AtlFlagCopy);
1051+
1052+ return pCol->QueryInterface(pVal);
10381053 }
10391054
10401055
@@ -1176,17 +1191,22 @@ STDMETHODIMP CControl::get_TreeRoot(VARIANT *pVal)
11761191 }
11771192 ::VariantInit(pVal);
11781193 if (!lstrcmp(m_classname, WC_TREEVIEW)) {
1179- HTREEITEM hItem = TreeView_GetRoot(m_hWnd);
11801194 CComObject<CTreeItem>* pItem = NULL;
1181- if (SUCCEEDED(pItem->CreateInstance(&pItem))) {
1182- pItem->AddRef();
1183- pItem->SetParam(m_hWnd, hItem);
1184- IUnknown* pUnk = NULL;
1185- if (SUCCEEDED(pItem->QueryInterface(IID_IUnknown, (void**)&pUnk))) {
1186- pVal->vt = VT_UNKNOWN;
1187- pVal->punkVal = pUnk;
1188- }
1195+ HRESULT hr;
1196+ if (FAILED(hr = CComObject<CTreeItem>::CreateInstance(&pItem))) {
1197+ return hr;
1198+ }
1199+
1200+ HTREEITEM hItem = TreeView_GetRoot(m_hWnd);
1201+ pItem->SetParam(m_hWnd, hItem);
1202+
1203+ IUnknown* pUnk = NULL;
1204+ if (FAILED(hr = pItem->QueryInterface(IID_IUnknown, (void**)&pUnk))) {
1205+ delete pItem;
1206+ return hr;
11891207 }
1208+ pVal->vt = VT_UNKNOWN;
1209+ pVal->punkVal = pUnk;
11901210 }
11911211 return S_OK;
11921212 }
--- a/Draw.cpp
+++ b/Draw.cpp
@@ -7,6 +7,31 @@
77 /////////////////////////////////////////////////////////////////////////////
88 // CCanvas
99
10+HRESULT CCanvas::FinalConstruct()
11+{
12+ // 派生元関連
13+ m_hParent = NULL;
14+
15+ // 印刷関連
16+ m_pPrinterDeviceMode = NULL;
17+ m_marginWidth = 150; // 1.5Cmのマージン
18+ m_marginHeight = 150;
19+
20+ // レイヤーの初期化
21+ for (int i = 0; i < MAXLAYER; i++) {
22+ m_pComLayer[i] = NULL;
23+ }
24+ for (int i = 0; i < MAXLAYER; i++) {
25+ HRESULT hr = CComObject<CLayer>::CreateInstance(&m_pComLayer[i]);
26+ if (FAILED(hr)) {
27+ return hr;
28+ }
29+ m_pComLayer[i]->AddRef();
30+ }
31+
32+ return S_OK;
33+}
34+
1035 void CCanvas::FinalRelease()
1136 {
1237 ATLTRACE("CCanvas::FinalRelease\r\n");
@@ -15,9 +40,9 @@ void CCanvas::FinalRelease()
1540 delete m_pPrinterDeviceMode;
1641 m_pPrinterDeviceMode = NULL;
1742 }
43+
1844 // レイヤーオブジェクトの解放
19- int i;
20- for (i = 0; i < MAXLAYER; i++) {
45+ for (int i = 0; i < MAXLAYER; i++) {
2146 if (m_pComLayer[i] != NULL) {
2247 m_pComLayer[i]->Release();
2348 m_pComLayer[i] = NULL;
@@ -25,19 +50,6 @@ void CCanvas::FinalRelease()
2550 }
2651 }
2752
28-STDMETHODIMP CCanvas::InterfaceSupportsErrorInfo(REFIID riid)
29-{
30- static const IID* arr[] =
31- {
32- &IID_ICanvas
33- };
34- for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
35- if (IsEqualGUID(*arr[i], riid))
36- return S_OK;
37- }
38- return S_FALSE;
39-}
40-
4153 STDMETHODIMP CCanvas::get_Layer(VARIANT varLay, VARIANT *pVal)
4254 {
4355 // レイヤーオブジェクトの受け渡し
--- a/Draw.h
+++ b/Draw.h
@@ -13,31 +13,13 @@
1313 class ATL_NO_VTABLE CCanvas :
1414 public CComObjectRootEx<CComSingleThreadModel>,
1515 public CComCoClass<CCanvas, &CLSID_Canvas>,
16- public ISupportErrorInfo,
16+ public ISupportErrorInfoImpl<&IID_ICanvas>,
1717 public IConnectionPointContainerImpl<CCanvas>,
1818 public IDispatchImpl<ICanvas, &IID_ICanvas, &LIBID_SERAPHYSCRIPTTOOLSLib>
1919 {
2020 public:
21- CCanvas()
22- {
23- // 派生元関連
24- m_hParent = NULL;
25- // 印刷関連
26- m_pPrinterDeviceMode = NULL;
27- m_marginWidth = 150; // 1.5Cmのマージン
28- m_marginHeight = 150;
29- // レイヤーの初期化
30- int i;
31- for (i = 0; i < MAXLAYER; i++) {
32- if (m_pComLayer[i]->CreateInstance(&m_pComLayer[i]) == S_OK) {
33- m_pComLayer[i]->AddRef();
34- }
35- else {
36- // 生成に失敗。
37- m_pComLayer[i] = NULL;
38- }
39- }
40- }
21+ HRESULT FinalConstruct();
22+
4123 void CCanvas::FinalRelease();
4224
4325 DECLARE_REGISTRY_RESOURCEID(IDR_CANVAS)
@@ -54,9 +36,6 @@ public:
5436 END_CONNECTION_POINT_MAP()
5537
5638
57- // ISupportsErrorInfo
58- STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
59-
6039 // ICanvas
6140 public:
6241 STDMETHOD(LoadPicture)(/*[in]*/VARIANT path,/*[out,retval]*/VARIANT* punkVal);
--- a/Form.cpp
+++ b/Form.cpp
@@ -32,7 +32,7 @@ STDMETHODIMP CForm::get_Control(VARIANT varNum, VARIANT *pVal)
3232 nID = tmp.iVal;
3333 }
3434 if (nID > 0) {
35- list<CComObject<CControl>*>::iterator p = m_lstControl.begin();
35+ std::list<CComObject<CControl>*>::iterator p = m_lstControl.begin();
3636 while (p != m_lstControl.end()) {
3737 if ((*p)->GetID() == nID) {
3838 // 同一IDを発見したので、これを返す
@@ -82,7 +82,7 @@ STDMETHODIMP CForm::SetControlFont(VARIANT fontname, VARIANT fontsize)
8282 m_nControlFontSize = siz;
8383
8484 // 現在のコントロールすべてに適用する(生成されていれば)
85- list<CComObject<CControl>*>::iterator p = m_lstControl.begin();
85+ std::list<CComObject<CControl>*>::iterator p = m_lstControl.begin();
8686 while (p != m_lstControl.end()) {
8787 (*p)->SetFont(m_hControlFont);
8888 p++;
@@ -234,7 +234,7 @@ STDMETHODIMP CForm::CheckListView(VARIANT colum, VARIANT width, VARIANT height,
234234 STDMETHODIMP CForm::ClearControls()
235235 {
236236 // コントロールをすべて破棄する
237- list<CComObject<CControl>*>::iterator p = m_lstControl.begin();
237+ std::list<CComObject<CControl>*>::iterator p = m_lstControl.begin();
238238 while (p != m_lstControl.end()) {
239239 (*p)->Destroy(); // ウィンドウを破棄し参照が残ってもアクセス不可にする
240240 (*p)->Release();
@@ -295,8 +295,9 @@ CControl* CForm::CreateControlCore(VARIANT &text, VARIANT &width, VARIANT &heigh
295295
296296 // インスタンスの生成
297297 CComObject<CControl>* pControl = NULL;
298- HRESULT hRet = pControl->CreateInstance(&pControl);
299- ATLASSERT(hRet == S_OK);
298+ HRESULT hRet = CComObject<CControl>::CreateInstance(&pControl);
299+ // FIXME: エラーを返せるようにすべき
300+ ATLASSERT(SUCCEEDED(hRet));
300301
301302 // 参照カウント、ポインタの保存
302303 pControl->AddRef();
@@ -315,7 +316,7 @@ CControl* CForm::CreateControlCore(VARIANT &text, VARIANT &width, VARIANT &heigh
315316 // このインターフェイスを戻り値とする
316317 IUnknown* pUnk = NULL;
317318 hRet = pControl->QueryInterface(IID_IUnknown, (void**)&pUnk);
318- ATLASSERT(hRet == S_OK);
319+ ATLASSERT(SUCCEEDED(hRet));
319320 ::VariantInit(pvarUnk);
320321 pvarUnk->vt = VT_UNKNOWN;
321322 pvarUnk->punkVal = pUnk;
@@ -401,7 +402,7 @@ void CForm::AttachOwner(HWND hOwner)
401402 {
402403 m_hOwner = hOwner;
403404 // 事前作成されていたコントロールをすべて生成する
404- list<CComObject<CControl>*>::iterator p = m_lstControl.begin();
405+ std::list<CComObject<CControl>*>::iterator p = m_lstControl.begin();
405406 while (p != m_lstControl.end()) {
406407 (*p)->Create(hOwner);
407408 (*p)->SetFont(m_hControlFont);
@@ -455,7 +456,7 @@ void CForm::EnableAllControl(BOOL mode)
455456 // メインウィンドウが作成されていなければ何もしない
456457 return;
457458 }
458- list<CComObject<CControl>*>::iterator p = m_lstControl.begin();
459+ std::list<CComObject<CControl>*>::iterator p = m_lstControl.begin();
459460 while (p != m_lstControl.end()) {
460461 (*p)->put_Enable(mode);
461462 p++;
@@ -492,7 +493,7 @@ BOOL CForm::FindControlEventName(int eventcode, BSTR *pEventName)
492493 {
493494 // pEventNameは初期化されていないBSTRへのポインタを渡す
494495 // 呼び出し元はtrueが帰ったら、このBSTRを解放する必要がある
495- list<CComObject<CControl>*>::iterator p = m_lstControl.begin();
496+ std::list<CComObject<CControl>*>::iterator p = m_lstControl.begin();
496497 while (p != m_lstControl.end()) {
497498 if ((*p)->GetID() == eventcode) {
498499 (*p)->GetClassEvent(pEventName);
--- a/Form.h
+++ b/Form.h
@@ -3,7 +3,6 @@
33 #pragma once
44
55 #include <list>
6-using namespace std;
76
87 #include "resource.h" // メイン シンボル
98 #include "control.h"
--- a/Instance.cpp
+++ b/Instance.cpp
@@ -8,47 +8,70 @@
88 /////////////////////////////////////////////////////////////////////////////
99 // CInstance
1010
11-CInstance::CInstance()
11+HRESULT CInstance::FinalConstruct()
1212 {
13+ HRESULT hr;
14+
1315 // メインウィンドウの生成
1416 m_pMainWindow = NULL;
15- if (m_pMainWindow->CreateInstance(&m_pMainWindow) == S_OK) {
16- m_pMainWindow->AddRef();
17- // オーバーラップウィンドウリストに追加
18- m_lstOverlappedWnd.push_back(m_pMainWindow);
17+ if (FAILED(hr = CComObject<COverlappedWindow>::CreateInstance(&m_pMainWindow))) {
18+ ATLASSERT(SUCCEEDED(hr));
19+ return hr;
1920 }
21+ m_pMainWindow->AddRef(); // インスタンス変数に保持する参照カウンタ+1
22+
2023 // コモンダイアログインターフェイスの生成
2124 m_pCommDlg = NULL;
22- if (m_pCommDlg->CreateInstance(&m_pCommDlg) == S_OK) {
23- m_pCommDlg->AddRef();
24- // メインウィンドウをコモンダイアログインターフェイスに接続する
25- if (m_pMainWindow) {
26- IUnknown* pUnk = NULL;
27- if (m_pMainWindow->QueryInterface(IID_IUnknown, (void**)&pUnk) == S_OK) {
28- CComVariant varUnk(pUnk);
29- m_pCommDlg->SetMainWindow(varUnk);
30- }
31- }
25+ if (FAILED(hr = CComObject<CCommDialog>::CreateInstance(&m_pCommDlg))) {
26+ ATLASSERT(SUCCEEDED(hr));
27+ // メインウィンドウは破棄する.
28+ m_pMainWindow->Release();
29+ return hr;
3230 }
31+ m_pCommDlg->AddRef();
32+
33+ // メインウィンドウをコモンダイアログインターフェイスに接続する
34+ CComPtr<IUnknown> pUnk;
35+ if (FAILED(hr = m_pMainWindow->QueryInterface(&pUnk))) {
36+ m_pCommDlg->Release();
37+ m_pMainWindow->Release();
38+ return hr;
39+ }
40+
41+ CComVariant varUnk(pUnk);
42+ m_pCommDlg->SetMainWindow(varUnk);
43+
44+ // オーバーラップウィンドウリストに追加する参照カウンタ+1
45+ m_pMainWindow->AddRef();
46+ m_lstOverlappedWnd.push_back(m_pMainWindow);
47+
3348 // ウェイトカーソル・カウント
3449 m_dWaitCursor = 0;
50+
51+ return S_OK;
3552 }
3653
3754 void CInstance::FinalRelease()
3855 {
3956 ATLTRACE("CInstance::FinalRelease\r\n");
57+
4058 // メインウィンドウの解放
59+ ATLTRACE(_TEXT("*refcount=%d\n"), m_pMainWindow->m_dwRef);
4160 if (m_pMainWindow) {
4261 m_pMainWindow->Release();
43- m_pMainWindow = NULL;
62+ //m_pMainWindow = NULL;
4463 }
64+
4565 // コモンダイアログインターフェイスの解放
66+ ATLTRACE(_TEXT("*refcount=%d\n"), m_pMainWindow->m_dwRef);
4667 if (m_pCommDlg) {
4768 m_pCommDlg->Release();
4869 m_pCommDlg = NULL;
4970 }
71+
5072 // ポップアップウィンドウの解放
51- list<CComObject<COverlappedWindow>*>::iterator p = m_lstOverlappedWnd.begin();
73+ ATLTRACE(_TEXT("*refcount=%d\n"), m_pMainWindow->m_dwRef);
74+ std::list<CComObject<COverlappedWindow>*>::iterator p = m_lstOverlappedWnd.begin();
5275 while (p != m_lstOverlappedWnd.end()) {
5376 (*p)->Close();
5477 (*p)->Release();
@@ -58,29 +81,33 @@ void CInstance::FinalRelease()
5881
5982 STDMETHODIMP CInstance::get_Dialog(VARIANT *pVal)
6083 {
84+ if (!pVal) {
85+ return E_POINTER;
86+ }
6187 // コモンダイアログインターフェイスを返す
6288 ::VariantInit(pVal);
6389 if (m_pCommDlg) {
64- IUnknown *pUnk = NULL;
65- if (m_pCommDlg->QueryInterface(IID_IUnknown, (void**)&pUnk) == S_OK) {
66- pVal->vt = VT_UNKNOWN;
67- pVal->punkVal = pUnk;
90+ HRESULT hr;
91+ CComPtr<IUnknown> pUnk;
92+ if (FAILED(hr = m_pCommDlg->QueryInterface(&pUnk))) {
93+ return hr;
6894 }
95+ pVal->vt = VT_UNKNOWN;
96+ pVal->punkVal = pUnk.Detach();
6997 }
7098 return S_OK;
7199 }
72100
73-STDMETHODIMP CInstance::CreateFrame(VARIANT *pvarUnk)
101+void CInstance::PurgeUnusedWindows()
74102 {
75- ::VariantInit(pvarUnk);
76103 // 参照カウントが1つしかないウィンドウの破棄を行う
77- list<CComObject<COverlappedWindow>*>::iterator p = m_lstOverlappedWnd.begin();
104+ std::list<CComObject<COverlappedWindow>*>::iterator p = m_lstOverlappedWnd.begin();
78105 while (p != m_lstOverlappedWnd.end()) {
79106 if ((*p)->m_dwRef == 1) {
80107 // 参照カウントが1しかない = このクラスしか使っていない = 不要
81108 BOOL bVisible = false;
82- (*p)->get_Visible(&bVisible);
83- if (!bVisible) {
109+ HRESULT hr = (*p)->get_Visible(&bVisible);
110+ if (SUCCEEDED(hr) && !bVisible) {
84111 // 表示されていなければ消してよし。
85112 (*p)->Release();
86113 p = m_lstOverlappedWnd.erase(p);
@@ -89,24 +116,53 @@ STDMETHODIMP CInstance::CreateFrame(VARIANT *pvarUnk)
89116 }
90117 p++;
91118 }
119+}
120+
121+STDMETHODIMP CInstance::CreateFrame(VARIANT *pvarUnk)
122+{
123+ if (!pvarUnk) {
124+ return E_POINTER;
125+ }
126+
127+ ::VariantInit(pvarUnk);
128+
129+ // 未使用のウィンドウを削除する
130+ PurgeUnusedWindows();
131+
132+ HRESULT hr;
133+
92134 // ウィンドウの生成
93135 CComObject<COverlappedWindow>* pNewWnd = NULL;
94- if (pNewWnd->CreateInstance(&pNewWnd) == S_OK) {
95- pNewWnd->AddRef();
96- pNewWnd->put_WaitCursor(m_dWaitCursor);
97- m_lstOverlappedWnd.push_back(pNewWnd);
98- // インターフェイスの取得
99- IUnknown* pUnk = NULL;
100- if (pNewWnd->QueryInterface(IID_IUnknown, (void**)&pUnk) == S_OK) {
101- pvarUnk->vt = VT_UNKNOWN;
102- pvarUnk->punkVal = pUnk;
103- }
136+ if (FAILED(hr = CComObject<COverlappedWindow>::CreateInstance(&pNewWnd))) {
137+ return hr;
138+ }
139+
140+ // インターフェイスの取得
141+ CComPtr<IUnknown> pUnk;
142+ if (FAILED(hr = pNewWnd->QueryInterface(&pUnk))) {
143+ delete pNewWnd;
144+ return hr;
104145 }
146+
147+ // ウェイトカーソル状態の設定
148+ pNewWnd->put_WaitCursor(m_dWaitCursor);
149+
150+ // 参照カウントの追加および
151+ // 管理ウィンドウリストへの保存
152+ pNewWnd->AddRef();
153+ m_lstOverlappedWnd.push_back(pNewWnd);
154+
155+ pvarUnk->vt = VT_UNKNOWN;
156+ pvarUnk->punkVal = pUnk.Detach();
105157 return S_OK;
106158 }
107159
108160 STDMETHODIMP CInstance::WaitEvent(VARIANT varTim, VARIANT *pvarUnk)
109161 {
162+ if (!pvarUnk) {
163+ return E_POINTER;
164+ }
165+
110166 ::VariantInit(pvarUnk);
111167 // 待機時間の取得
112168 DWORD sleeptim = 1000;
@@ -120,10 +176,12 @@ STDMETHODIMP CInstance::WaitEvent(VARIANT varTim, VARIANT *pvarUnk)
120176 // すべてのポップアップウィンドウのイベントハンドルを取得する
121177 HANDLE hEvent[MAXIMUM_WAIT_OBJECTS] = {NULL};
122178 HWND hWnd[MAXIMUM_WAIT_OBJECTS] = {NULL};
123- CComObject<COverlappedWindow>* pOverlapped[MAXIMUM_WAIT_OBJECTS] = {NULL};
179+
180+ CComObject<COverlappedWindow>* pOverlapped[MAXIMUM_WAIT_OBJECTS] = {0};
181+
124182 int count = 0;
125183 int n = 0;
126- list<CComObject<COverlappedWindow>*>::iterator p = m_lstOverlappedWnd.begin();
184+ std::list<CComObject<COverlappedWindow>*>::iterator p = m_lstOverlappedWnd.begin();
127185 while (p != m_lstOverlappedWnd.end()) {
128186 n = count;
129187 (*p)->SetWaitParam(&count, hWnd, hEvent);
@@ -132,16 +190,17 @@ STDMETHODIMP CInstance::WaitEvent(VARIANT varTim, VARIANT *pvarUnk)
132190 }
133191 p++;
134192 }
193+
135194 // メッセージループ
136195 if (count > 0) {
137196 DWORD ret = pOverlapped[0]->MessageLoop(sleeptim, count, hWnd, hEvent);
138197 if (ret > 0 && ret <= (DWORD)count) {
139198 if (pOverlapped[ret - 1]) {
140199 // OVERLAPPEDWINDOWオブジェクトへのインターフェイスを返す
141- IUnknown* pUnk = NULL;
142- if (pOverlapped[ret - 1]->QueryInterface(IID_IUnknown, (void**)&pUnk) == S_OK) {
200+ CComPtr<IUnknown> pUnk;
201+ if (SUCCEEDED(pOverlapped[ret - 1]->QueryInterface(&pUnk))) {
143202 pvarUnk->vt = VT_UNKNOWN;
144- pvarUnk->punkVal = pUnk;
203+ pvarUnk->punkVal = pUnk.Detach();
145204 }
146205 }
147206 }
@@ -151,28 +210,40 @@ STDMETHODIMP CInstance::WaitEvent(VARIANT varTim, VARIANT *pvarUnk)
151210
152211 STDMETHODIMP CInstance::get_MainFrame(VARIANT *pVal)
153212 {
213+ if (!pVal) {
214+ return E_POINTER;
215+ }
216+
154217 ::VariantInit(pVal);
155218 if (m_pMainWindow) {
156- IUnknown* pUnk = NULL;
157- if (m_pMainWindow->QueryInterface(IID_IUnknown, (void**)&pUnk) == S_OK) {
158- pVal->vt = VT_UNKNOWN;
159- pVal->punkVal = pUnk;
219+ HRESULT hr;
220+ CComPtr<IUnknown> pUnk;
221+ if (FAILED(hr = m_pMainWindow->QueryInterface(&pUnk))) {
222+ return hr;
160223 }
224+ pVal->vt = VT_UNKNOWN;
225+ pVal->punkVal = pUnk.Detach();
161226 }
162227 return S_OK;
163228 }
164229
165230 STDMETHODIMP CInstance::get_WaitCursor(short *pVal)
166231 {
232+ if (!pVal) {
233+ return E_POINTER;
234+ }
235+
167236 *pVal = m_dWaitCursor;
237+
168238 return S_OK;
169239 }
170240
171241 STDMETHODIMP CInstance::put_WaitCursor(short newVal)
172242 {
173243 m_dWaitCursor = newVal;
244+
174245 // すべてのポップアップウィンドウにウェイトカーソル値を設定する
175- list<CComObject<COverlappedWindow>*>::iterator p = m_lstOverlappedWnd.begin();
246+ std::list<CComObject<COverlappedWindow>*>::iterator p = m_lstOverlappedWnd.begin();
176247 while (p != m_lstOverlappedWnd.end()) {
177248 (*p)->put_WaitCursor(newVal);
178249 p++;
@@ -182,9 +253,14 @@ STDMETHODIMP CInstance::put_WaitCursor(short newVal)
182253
183254 STDMETHODIMP CInstance::get_Keyboard(VARIANT vk, BOOL *pVal)
184255 {
256+ if (!pVal) {
257+ return E_POINTER;
258+ }
259+
260+ HRESULT hr;
185261 CComVariant varVk;
186- if (varVk.ChangeType(VT_I2, &vk) != S_OK) {
187- return DISP_E_TYPEMISMATCH;
262+ if (FAILED(hr = varVk.ChangeType(VT_I2, &vk))) {
263+ return hr;
188264 }
189265 *pVal = (GetAsyncKeyState(varVk.iVal) & 0x8000) ? VB_TRUE : VB_FALSE;
190266 return S_OK;
@@ -192,22 +268,37 @@ STDMETHODIMP CInstance::get_Keyboard(VARIANT vk, BOOL *pVal)
192268
193269 STDMETHODIMP CInstance::get_MousePosX(long *pVal)
194270 {
271+ if (!pVal) {
272+ return E_POINTER;
273+ }
274+
195275 POINT pt;
196276 ::GetCursorPos(&pt);
197277 *pVal = pt.x;
278+
198279 return S_OK;
199280 }
200281
201282 STDMETHODIMP CInstance::get_MousePosY(long *pVal)
202283 {
284+ if (!pVal) {
285+ return E_POINTER;
286+ }
287+
203288 POINT pt;
204289 ::GetCursorPos(&pt);
205290 *pVal = pt.y;
291+
206292 return S_OK;
207293 }
208294
209295 STDMETHODIMP CInstance::get_Version(double *pVal)
210296 {
211- *pVal = 0.92;
297+ if (!pVal) {
298+ return E_POINTER;
299+ }
300+
301+ *pVal = 0.93;
302+
212303 return S_OK;
213304 }
--- a/Instance.h
+++ b/Instance.h
@@ -12,26 +12,26 @@
1212 // CInstance
1313 class ATL_NO_VTABLE CInstance :
1414 public CComObjectRootEx<CComSingleThreadModel>,
15- public CStockPropImpl<CInstance, ISeraphyScriptTools_Instance, &IID_ISeraphyScriptTools_Instance, &LIBID_SERAPHYSCRIPTTOOLSLib>,
15+ public CComCoClass<CInstance, &CLSID_SeraphyScriptTools_Instance>,
16+ public ISupportErrorInfoImpl<&IID_ISeraphyScriptTools_Instance>,
1617 public CComControl<CInstance>,
18+ public CStockPropImpl<CInstance, ISeraphyScriptTools_Instance, &IID_ISeraphyScriptTools_Instance, &LIBID_SERAPHYSCRIPTTOOLSLib>,
1719 public IPersistStreamInitImpl<CInstance>,
1820 public IOleControlImpl<CInstance>,
1921 public IOleObjectImpl<CInstance>,
2022 public IOleInPlaceActiveObjectImpl<CInstance>,
2123 public IViewObjectExImpl<CInstance>,
2224 public IOleInPlaceObjectWindowlessImpl<CInstance>,
23- public ISupportErrorInfo,
2425 public IConnectionPointContainerImpl<CInstance>,
2526 public IPersistStorageImpl<CInstance>,
2627 public ISpecifyPropertyPagesImpl<CInstance>,
2728 public IQuickActivateImpl<CInstance>,
2829 public IDataObjectImpl<CInstance>,
2930 public IProvideClassInfo2Impl<&CLSID_SeraphyScriptTools_Instance, &DIID__ISeraphyScriptTools_InstanceEvents, &LIBID_SERAPHYSCRIPTTOOLSLib>,
30- public IPropertyNotifySinkCP<CInstance>,
31- public CComCoClass<CInstance, &CLSID_SeraphyScriptTools_Instance>
31+ public IPropertyNotifySinkCP<CInstance>
3232 {
3333 public:
34- CInstance();
34+ HRESULT FinalConstruct();
3535 void FinalRelease();
3636
3737 DECLARE_REGISTRY_RESOURCEID(IDR_INSTANCE)
@@ -84,22 +84,6 @@ public:
8484 // LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
8585 // LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);
8686
87-
88-
89- // ISupportsErrorInfo
90- STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid)
91- {
92- static const IID* arr[] =
93- {
94- &IID_ISeraphyScriptTools_Instance,
95- };
96- for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
97- if (IsEqualGUID(*arr[i], riid))
98- return S_OK;
99- }
100- return S_FALSE;
101- }
102-
10387 // IViewObjectEx
10488 DECLARE_VIEW_STATUS(VIEWSTATUS_SOLIDBKGND | VIEWSTATUS_OPAQUE)
10589
@@ -117,6 +101,7 @@ public:
117101 STDMETHOD(CreateFrame)(/*[out,retval]*/VARIANT* pvarUnk);
118102 STDMETHOD(get_Dialog)(/*[out, retval]*/ VARIANT *pVal);
119103
104+protected:
120105 HRESULT OnDraw(ATL_DRAWINFO& di)
121106 {
122107 RECT& rc = *(RECT*)di.prcBounds;
@@ -132,10 +117,14 @@ public:
132117
133118 return S_OK;
134119 }
135- CComBSTR m_bstrCaption;
120+
121+public:
122+ CComBSTR m_bstrCaption; // FIXME: protectedにする
123+
136124 protected:
137- list<CComObject<COverlappedWindow>*> m_lstOverlappedWnd;
138- CComObject<CCommDialog>* m_pCommDlg;
139- CComObject<COverlappedWindow>* m_pMainWindow;
125+ void PurgeUnusedWindows();
126+ std::list<CComObject<COverlappedWindow>*> m_lstOverlappedWnd;
127+ CComObject<CCommDialog>* m_pCommDlg; //FIXME: CComPtrへ
128+ CComObject<COverlappedWindow>* m_pMainWindow; //FIXME: CComPtrへ
140129 int m_dWaitCursor;
141130 };
--- a/Layer.cpp
+++ b/Layer.cpp
@@ -36,7 +36,7 @@ void CLayer::Draw(CDC dc)
3636 }
3737 // 描画データ
3838 EnterCriticalSection(&m_objDrawingDataProtection);
39- list<drawdata*>::iterator p = m_lstDraw.begin();
39+ std::list<drawdata*>::iterator p = m_lstDraw.begin();
4040 while (p != m_lstDraw.end()) {
4141 (*p)->Draw(dc);
4242 p++;
@@ -266,7 +266,7 @@ STDMETHODIMP CLayer::Clear()
266266 {
267267 // ドローイングデーターの破棄
268268 EnterCriticalSection(&m_objDrawingDataProtection);
269- list<drawdata*>::iterator p = m_lstDraw.begin();
269+ std::list<drawdata*>::iterator p = m_lstDraw.begin();
270270 while (p != m_lstDraw.end()) {
271271 (*p)->Destroy();
272272 p = m_lstDraw.erase(p);
--- a/Layer.h
+++ b/Layer.h
@@ -5,7 +5,6 @@
55 #include "resource.h" // メイン シンボル
66
77 #include <list>
8-using namespace std;
98
109
1110 /////////////////////////////////////////////////////////////////////////////
@@ -596,7 +595,7 @@ public:
596595 void AddDrawData(drawdata* pDrawData);
597596 protected:
598597 CRITICAL_SECTION m_objDrawingDataProtection;
599- list<drawdata*> m_lstDraw;
598+ std::list<drawdata*> m_lstDraw;
600599 DWORD m_dwFillColor;
601600 DWORD m_dwFontColor;
602601 DWORD m_dwColor;
--- a/ObjectMap.cpp
+++ b/ObjectMap.cpp
@@ -5,11 +5,16 @@
55 #include "profilesection.h"
66 #include "CComEnumDynaVARIANT.h"
77
8+#include <vector>
9+
810 /////////////////////////////////////////////////////////////////////////////
911 // CObjectMap
1012
1113 STDMETHODIMP CObjectMap::FindNear(VARIANT key, VARIANT *pVal)
1214 {
15+ if (!pVal) {
16+ return E_POINTER;
17+ }
1318 ::VariantInit(pVal);
1419
1520 CComVariant varName;
@@ -23,13 +28,16 @@ STDMETHODIMP CObjectMap::FindNear(VARIANT key, VARIANT *pVal)
2328 // 発見された
2429 CComVariant findkey((LPCWSTR)p->first);
2530 findkey.ChangeType(VT_BSTR);
26- findkey.Detach(pVal);
31+ return findkey.Detach(pVal);
2732 }
28- return S_OK;
33+ return S_FALSE;
2934 }
3035
3136 STDMETHODIMP CObjectMap::get_NearValue(VARIANT key, VARIANT *pVal)
3237 {
38+ if (!pVal) {
39+ return E_POINTER;
40+ }
3341 ::VariantInit(pVal);
3442
3543 CComVariant varName;
@@ -41,13 +49,16 @@ STDMETHODIMP CObjectMap::get_NearValue(VARIANT key, VARIANT *pVal)
4149 VariantMap::iterator p = m_mapVariant.lower_bound(varName.bstrVal);
4250 if (p != m_mapVariant.end()) {
4351 // 発見された
44- VariantCopy(pVal, &p->second);
52+ return VariantCopy(pVal, &p->second);
4553 }
46- return S_OK;
54+ return S_FALSE;
4755 }
4856
4957 STDMETHODIMP CObjectMap::get_Value(VARIANT key, VARIANT *pVal)
5058 {
59+ if (!pVal) {
60+ return E_POINTER;
61+ }
5162 ::VariantInit(pVal);
5263
5364 CComVariant varName;
@@ -59,9 +70,11 @@ STDMETHODIMP CObjectMap::get_Value(VARIANT key, VARIANT *pVal)
5970 VariantMap::iterator p = m_mapVariant.find(varName.bstrVal);
6071 if (p != m_mapVariant.end()) {
6172 // 発見された
62- VariantCopy(pVal, &p->second);
73+ return VariantCopy(pVal, &p->second);
6374 }
64- return S_OK;
75+
76+ // 見つからなかった
77+ return S_FALSE;
6578 }
6679
6780 STDMETHODIMP CObjectMap::put_Value(VARIANT key, VARIANT newVal)
@@ -75,20 +88,20 @@ STDMETHODIMP CObjectMap::put_Value(VARIANT key, VARIANT newVal)
7588 VariantMap::iterator p = m_mapVariant.find(varName.bstrVal);
7689 if (p != m_mapVariant.end()) {
7790 // 既存
78- VariantCopy(&p->second, &newVal);
91+ p->second = newVal;
7992 }
8093 else {
8194 // 新規
82- VARIANT tmp;
83- ::VariantInit(&tmp);
84- VariantCopy(&tmp, &newVal);
85- m_mapVariant.insert(pair<_bstr_t, VARIANT>(varName.bstrVal, tmp));
95+ m_mapVariant.insert(std::make_pair(varName.bstrVal, newVal));
8696 }
8797 return S_OK;
8898 }
8999
90100 STDMETHODIMP CObjectMap::get_Count(long *pVal)
91101 {
102+ if (!pVal) {
103+ return E_POINTER;
104+ }
92105 *pVal = m_mapVariant.size();
93106 return S_OK;
94107 }
@@ -98,7 +111,7 @@ STDMETHODIMP CObjectMap::Clear()
98111 //VARIANTのクリアと連想配列の解放
99112 VariantMap::iterator p = m_mapVariant.begin();
100113 while (p != m_mapVariant.end()) {
101- ::VariantClear(&p->second);
114+ p->second.Clear();
102115 p++;
103116 }
104117 m_mapVariant.clear();
@@ -108,73 +121,90 @@ STDMETHODIMP CObjectMap::Clear()
108121
109122 STDMETHODIMP CObjectMap::Duplicate(IUnknown** punkVal)
110123 {
124+ if (!punkVal) {
125+ return E_POINTER;
126+ }
111127 *punkVal = NULL;
128+
112129 CComObject<CObjectMap>* pMap = NULL;
113- if (pMap->CreateInstance(&pMap) == S_OK) {
114- // 現在のオブジェクトを複製する
115- VariantMap::iterator p = m_mapVariant.begin();
116- while (p != m_mapVariant.end()) {
117- CComVariant key((LPCWSTR)p->first);
118- key.ChangeType(VT_BSTR);
119- pMap->put_Value(key, p->second);
120- p++;
121- }
122- pMap->QueryInterface(IID_IUnknown, (void**)punkVal);
130+ HRESULT hr;
131+ if (FAILED(hr = CComObject<CObjectMap>::CreateInstance(&pMap))) {
132+ return hr;
123133 }
124- return S_OK;
134+
135+ // 現在のオブジェクトを複製する
136+ VariantMap::iterator p = m_mapVariant.begin();
137+ while (p != m_mapVariant.end()) {
138+ CComVariant key(p->first);
139+ key.ChangeType(VT_BSTR);
140+ pMap->put_Value(key, p->second);
141+ p++;
142+ }
143+
144+ return pMap->QueryInterface(punkVal);
125145 }
126146
127147 STDMETHODIMP CObjectMap::CreateMap(IUnknown** punkVal)
128148 {
149+ if (!punkVal) {
150+ return E_POINTER;
151+ }
129152 *punkVal = NULL;
153+
130154 CComObject<CObjectMap>* pMap = NULL;
131- if (SUCCEEDED(pMap->CreateInstance(&pMap))) {
132- return pMap->QueryInterface(IID_IUnknown, (void**)punkVal);
155+ HRESULT hr;
156+ if (FAILED(hr = CComObject<CObjectMap>::CreateInstance(&pMap))) {
157+ return hr;
133158 }
134- return E_FAIL;
159+
160+ return pMap->QueryInterface(punkVal);
135161 }
136162
137163 STDMETHODIMP CObjectMap::get__NewEnum(IUnknown **pVal)
138164 {
165+ if (!pVal) {
166+ return E_POINTER;
167+ }
168+
139169 int mx = m_mapVariant.size();
140- VARIANT* pvarArray = new VARIANT[mx + 1];
170+ std::vector<CComVariant> pvarArray;
171+ pvarArray.resize(mx + 1);
172+
141173 // 格納されている名前の列挙
142174 VariantMap::iterator p = m_mapVariant.begin();
143175 int i = 0;
144176 while (p != m_mapVariant.end()) {
145- ::VariantInit(&pvarArray[i]);
146- pvarArray[i].vt = VT_BSTR;
147- pvarArray[i].bstrVal = SysAllocString(p->first);
177+ pvarArray[i] = p->first;
148178 p++;
149179 i++;
150180 }
181+
151182 // 列挙インターフェイスの生成
183+ HRESULT hr;
152184 CComObject<CComEnumVARIANT>* pCol = NULL;
153- if (pCol->CreateInstance(&pCol) == S_OK) {
154- pCol->AddRef();
155- pCol->Init(&pvarArray[0], &pvarArray[mx], pCol, AtlFlagCopy);
156- *pVal = pCol;
157- }
158- // 確保したバリアントの破棄(リリースを行う必要あり)
159- i = 0;
160- while (i < mx) {
161- ::VariantClear(&pvarArray[i++]);
185+ if (FAILED(hr = CComObject<CComEnumVARIANT>::CreateInstance(&pCol))) {
186+ return hr;
162187 }
163- delete[]pvarArray;
164- return S_OK;
188+ pCol->Init(&pvarArray[0], &pvarArray[mx], pCol, AtlFlagCopy);
189+
190+ return pCol->QueryInterface(pVal);
165191 }
166192
167193 STDMETHODIMP CObjectMap::ExpandVariables(VARIANT text, VARIANT env, VARIANT *pVal)
168194 {
169195 CComVariant varText, varEnv, varResult;
170- if (varText.ChangeType(VT_BSTR, &text) != S_OK) {
171- return DISP_E_TYPEMISMATCH;
196+
197+ HRESULT hr;
198+ if (FAILED(hr = varText.ChangeType(VT_BSTR, &text))) {
199+ return hr;
172200 }
201+
173202 // 環境変数を展開するか?
174203 BOOL bEnv = false;
175- if (varEnv.ChangeType(VT_I2, &env) == S_OK) {
204+ if (SUCCEEDED(varEnv.ChangeType(VT_I2, &env))) {
176205 bEnv = varEnv.iVal;
177206 }
207+
178208 // フェーズ1 : 含まれる変数を調査して必要なバッファサイズを求める
179209 // フェーズ2 ; 実際に展開する
180210 DWORD expandsize = 0;
@@ -213,7 +243,7 @@ STDMETHODIMP CObjectMap::ExpandVariables(VARIANT text, VARIANT env, VARIANT *pVa
213243 if (p != m_mapVariant.end()) {
214244 // 発見された
215245 CComVariant tmp;
216- if (tmp.ChangeType(VT_BSTR, &p->second) == S_OK) {
246+ if (SUCCEEDED(tmp.ChangeType(VT_BSTR, &p->second))) {
217247 if (phase == 0) {
218248 // フェーズ1はサイズをカウントするだけ
219249 expandsize += SysStringLen(tmp.bstrVal);
@@ -221,8 +251,7 @@ STDMETHODIMP CObjectMap::ExpandVariables(VARIANT text, VARIANT env, VARIANT *pVa
221251 else {
222252 // フェーズ2は現在位置に変数を展開する
223253 UINT len = SysStringLen(tmp.bstrVal);
224- UINT i;
225- for (i = 0; i < len; i++) {
254+ for (UINT i = 0; i < len; i++) {
226255 pExpandBuffer[writeidx++] = tmp.bstrVal[i];
227256 }
228257 }
@@ -268,7 +297,7 @@ STDMETHODIMP CObjectMap::ExpandVariables(VARIANT text, VARIANT env, VARIANT *pVa
268297 // フェーズ2が終了したので置換が完了した
269298 pExpandBuffer[writeidx] = 0;
270299 varResult = (LPCWSTR)pExpandBuffer;
271- delete[]pExpandBuffer;
300+ delete[] pExpandBuffer;
272301 }
273302 }
274303 varResult.Detach(pVal);
@@ -338,7 +367,7 @@ STDMETHODIMP CObjectMap::LoadProfile(IUnknown *punkVal)
338367 while (idx <= mx) {
339368 CComVariant varKey, varVal;
340369 if (SafeArrayGetElement(varArray.parray, &idx, &varKey) == S_OK) {
341- if (pSection->get_Value(varKey, &varVal) == S_OK) {
370+ if (SUCCEEDED(pSection->get_Value(varKey, &varVal))) {
342371 put_Value(varKey, varVal);
343372 }
344373 }
--- a/ObjectMap.h
+++ b/ObjectMap.h
@@ -5,9 +5,8 @@
55 #include "resource.h" // メイン シンボル
66 #include <map>
77 #include <string>
8-using namespace std;
98
10-typedef map<_bstr_t, VARIANT> VariantMap;
9+typedef std::map<CComBSTR, CComVariant> VariantMap;
1110
1211 /////////////////////////////////////////////////////////////////////////////
1312 // CObjectMap
@@ -18,9 +17,8 @@ class ATL_NO_VTABLE CObjectMap :
1817 public IDispatchImpl<IObjectMap, &IID_IObjectMap, &LIBID_SERAPHYSCRIPTTOOLSLib>
1918 {
2019 public:
21- CObjectMap()
22- {
23- }
20+ CObjectMap() {}
21+
2422 void FinalRelease()
2523 {
2624 Clear();
--- a/ObjectVector.cpp
+++ b/ObjectVector.cpp
@@ -10,20 +10,34 @@
1010
1111 STDMETHODIMP CObjectVector::CreateVector(IUnknown **punkVal)
1212 {
13+ if (!punkVal) {
14+ return E_POINTER;
15+ }
1316 *punkVal = NULL;
17+
1418 CComObject<CObjectVector>* pVct = NULL;
15- if (SUCCEEDED(pVct->CreateInstance(&pVct))) {
16- pVct->QueryInterface(IID_IUnknown, (void**)punkVal);
19+ HRESULT hr;
20+ if (FAILED(hr = CComObject<CObjectVector>::CreateInstance(&pVct))) {
21+ return hr;
1722 }
18- return S_OK;
23+
24+ return pVct->QueryInterface(punkVal);
1925 }
2026
2127 STDMETHODIMP CObjectVector::Duplicate(VARIANT idx, VARIANT count, IUnknown **punkVal)
2228 {
29+ if (!punkVal) {
30+ return E_POINTER;
31+ }
2332 *punkVal = NULL;
33+
2434 CComObject<CObjectVector>* pVct = NULL;
25- if (SUCCEEDED(pVct->CreateInstance(&pVct))) {
26- pVct->QueryInterface(IID_IUnknown, (void**)punkVal);
35+ HRESULT hr;
36+ if (FAILED(hr = CComObject<CObjectVector>::CreateInstance(&pVct))) {
37+ return hr;
38+ }
39+ if (FAILED(hr = pVct->QueryInterface(punkVal))) {
40+ return hr;
2741 }
2842
2943 if (!m_vctVariant.empty()) {
@@ -49,12 +63,8 @@ STDMETHODIMP CObjectVector::Duplicate(VARIANT idx, VARIANT count, IUnknown **pun
4963 }
5064
5165 if (nIdx < mx) {
52- long i;
53- for (i = 0; i < nCount; i++) {
54- VARIANT tmp;
55- ::VariantInit(&tmp);
56- ::VariantCopy(&tmp, &m_vctVariant.at(nIdx + i));
57- pVct->m_vctVariant.push_back(tmp);
66+ for (long i = 0; i < nCount; i++) {
67+ pVct->m_vctVariant.push_back(m_vctVariant[nIdx + i]);
5868 }
5969 }
6070 }
@@ -66,7 +76,7 @@ STDMETHODIMP CObjectVector::Clear()
6676 //VARIANTのクリアと連想配列の解放
6777 VariantVector::iterator p = m_vctVariant.begin();
6878 while (p != m_vctVariant.end()) {
69- ::VariantClear(&*p);
79+ p->Clear();
7080 p++;
7181 }
7282 m_vctVariant.clear();
@@ -102,10 +112,7 @@ STDMETHODIMP CObjectVector::Erase(VARIANT idx, VARIANT count)
102112 STDMETHODIMP CObjectVector::Push(VARIANT newVal)
103113 {
104114 // 末尾に追加
105- VARIANT tmp;
106- ::VariantInit(&tmp);
107- ::VariantCopy(&tmp, &newVal);
108- m_vctVariant.push_back(tmp);
115+ m_vctVariant.push_back(newVal);
109116 return S_OK;
110117 }
111118
@@ -116,7 +123,7 @@ STDMETHODIMP CObjectVector::Pop(VARIANT *pVal)
116123 if (!m_vctVariant.empty()) {
117124 long mx = m_vctVariant.size();
118125 ::VariantInit(pVal);
119- ::VariantCopy(pVal, &m_vctVariant.at(mx - 1));
126+ ::VariantCopy(pVal, &m_vctVariant[mx - 1]);
120127 m_vctVariant.pop_back();
121128 }
122129 return S_OK;
@@ -136,10 +143,7 @@ STDMETHODIMP CObjectVector::Insert(VARIANT idx, VARIANT newVal)
136143 return DISP_E_BADINDEX;
137144 }
138145
139- VARIANT tmp;
140- ::VariantInit(&tmp);
141- ::VariantCopy(&tmp, &newVal);
142- m_vctVariant.insert(m_vctVariant.begin() + nIdx, tmp);
146+ m_vctVariant.insert(m_vctVariant.begin() + nIdx, newVal);
143147 return S_OK;
144148 }
145149
@@ -160,7 +164,7 @@ STDMETHODIMP CObjectVector::get_Value(VARIANT idx, VARIANT *pVal)
160164 long mx = m_vctVariant.size();
161165 if (nIdx < mx) {
162166 // ベクターの範囲内なら値を取得する
163- ::VariantCopy(pVal, &m_vctVariant.at(nIdx));
167+ ::VariantCopy(pVal, &m_vctVariant[nIdx]);
164168 }
165169 return S_OK;
166170 }
@@ -202,11 +206,12 @@ STDMETHODIMP CObjectVector::get__NewEnum(IUnknown **pVal)
202206 {
203207 typedef CComEnumDynaVARIANT<CObjectVector> CComEnumDynaVector;
204208 CComObject<CComEnumDynaVector>* pDyna = NULL;
205- if (SUCCEEDED(pDyna->CreateInstance(&pDyna))) {
206- pDyna->Init(this, 0);
207- pDyna->QueryInterface(IID_IEnumVARIANT, (void**)pVal);
209+ HRESULT hr;
210+ if (FAILED(hr = CComObject<CComEnumDynaVector>::CreateInstance(&pDyna))) {
211+ return hr;
208212 }
209- return S_OK;
213+ pDyna->Init(this, 0);
214+ return pDyna->QueryInterface(IID_IEnumVARIANT, (void**)pVal);
210215 }
211216
212217 STDMETHODIMP CObjectVector::Merge(VARIANT unkVal)
--- a/ObjectVector.h
+++ b/ObjectVector.h
@@ -4,9 +4,8 @@
44
55 #include "resource.h" // メイン シンボル
66 #include <vector>
7-using namespace std;
87
9-typedef vector<VARIANT> VariantVector;
8+typedef std::vector<CComVariant> VariantVector;
109
1110 /////////////////////////////////////////////////////////////////////////////
1211 // CObjectVector
--- a/OverlappedWindow.cpp
+++ b/OverlappedWindow.cpp
@@ -14,7 +14,7 @@
1414 // COverlappedWindow
1515
1616
17-COverlappedWindow::COverlappedWindow()
17+HRESULT COverlappedWindow::FinalConstruct()
1818 {
1919 m_pUnkMarshaler = NULL;
2020
@@ -54,29 +54,38 @@ COverlappedWindow::COverlappedWindow()
5454 m_bDefaultAction = true; // ディフォルトのOK/CANCELアクションで閉じる
5555
5656 // フォームインターフェイスの作成
57- m_pForm = NULL;
5857 m_hLastFocusControl = NULL;
59- if (m_pForm->CreateInstance(&m_pForm) == S_OK) {
60- m_pForm->AddRef();
61- m_pForm->SetWindowSize(windowParam.width, windowParam.height,
62- windowParam.GetStyle(), windowParam.exstyle);
58+
59+
60+ HRESULT hr;
61+
62+ // フォームオブジェクトの生成
63+ m_pForm = NULL;
64+ if (FAILED(hr = CComObject<CForm>::CreateInstance(&m_pForm))) {
65+ return hr;
6366 }
64- // 描画インターフェイスの生成
67+ m_pForm->AddRef();
68+ m_pForm->SetWindowSize(windowParam.width, windowParam.height,
69+ windowParam.GetStyle(), windowParam.exstyle);
70+
71+ // 描画オブジェクトの生成
6572 m_pCanvas = NULL;
66- if (m_pCanvas->CreateInstance(&m_pCanvas) == S_OK) {
67- m_pCanvas->AddRef();
73+ if (FAILED(hr = CComObject<CCanvas>::CreateInstance(&m_pCanvas))) {
74+ return hr;
6875 }
69- // ユーザー定義連想配列インターフェイスの生成
76+ m_pCanvas->AddRef();
77+
78+ // ユーザー定義連想配列オブジェクトの生成
7079 m_pObject = NULL;
71- if (m_pObject->CreateInstance(&m_pObject) == S_OK) {
72- m_pObject->AddRef();
80+ if (FAILED(hr = CComObject<CObjectMap>::CreateInstance(&m_pObject))) {
81+ return hr;
7382 }
83+ m_pObject->AddRef();
84+
7485 // ウェイトカーソルの初期化
7586 m_dWaitCursor = 0;
76-}
7787
78-HRESULT COverlappedWindow::FinalConstruct()
79-{
88+ // 集約のためのフリースレッドマーシャラの設定
8089 return CoCreateFreeThreadedMarshaler(
8190 GetControllingUnknown(), &m_pUnkMarshaler.p);
8291 }
@@ -98,7 +107,7 @@ void COverlappedWindow::FinalRelease()
98107 ::DestroyIcon(m_hIcon);
99108 }
100109 // チャイルドポップアップの破棄
101- list<CComObject<COverlappedWindow>*>::iterator pWnd = m_lstChild.begin();
110+ std::list<CComObject<COverlappedWindow>*>::iterator pWnd = m_lstChild.begin();
102111 while (pWnd != m_lstChild.end()) {
103112 (*pWnd)->Close();
104113 (*pWnd)->Release();
@@ -135,7 +144,7 @@ void COverlappedWindow::FinalRelease()
135144
136145 EnterCriticalSection(&m_objEventDataProtection);
137146 // イベントデータの解放
138- list<CComObject<CEvent>*>::iterator pEv = m_lstEvent.begin();
147+ std::list<CComObject<CEvent>*>::iterator pEv = m_lstEvent.begin();
139148 while (pEv != m_lstEvent.end()) {
140149 (*pEv)->Release();
141150 pEv = m_lstEvent.erase(pEv);
@@ -654,9 +663,14 @@ STDMETHODIMP COverlappedWindow::DoEvent(VARIANT *varResult)
654663 }
655664 m_pEvent = pEv;
656665 m_pEvent->AddRef();
666+
657667 // このオブジェクトを引数として渡すためにインターフェイスを生成する
658- IUnknown* pUnk = NULL;
659- QueryInterface(IID_IUnknown, (void**)&pUnk);
668+ CComPtr<IUnknown> pUnk;
669+ HRESULT hr;
670+ if (FAILED(hr = QueryInterface(IID_IUnknown, (void**) &pUnk))) {
671+ return hr;
672+ }
673+
660674 // イベントに対するライズ
661675 switch (pEv->GetMessage()) {
662676 case WM_KEYDOWN:
@@ -789,7 +803,7 @@ STDMETHODIMP COverlappedWindow::DoEvent(VARIANT *varResult)
789803 }
790804 // メニューの検索
791805 if (m_hMenu && nID >= 100) {
792- map<int, CComBSTR>::iterator p = m_cMenuMap.find(nID);
806+ std::map<int, CComBSTR>::iterator p = m_cMenuMap.find(nID);
793807 if (p != m_cMenuMap.end()) {
794808 // 発見された
795809 ClassObjectInvoke(p->second);
@@ -823,7 +837,7 @@ STDMETHODIMP COverlappedWindow::DoEvent(VARIANT *varResult)
823837 }
824838 // この引数として渡したインターフェイスを解放する
825839 if (pUnk) {
826- pUnk->Release();
840+ pUnk.Release();
827841 }
828842 }
829843 // 処理されたイベントは解放する
@@ -847,7 +861,7 @@ void COverlappedWindow::AddEventSingle(int message, WPARAM wParam, LPARAM lParam
847861 // イベントバッファに未処理のイベントがあればイベントを発行しない。
848862 BOOL bFind = false;
849863 EnterCriticalSection(&m_objEventDataProtection);
850- list<CComObject<CEvent>*>::iterator p = m_lstEvent.begin();
864+ std::list<CComObject<CEvent>*>::iterator p = m_lstEvent.begin();
851865 while (p != m_lstEvent.end()) {
852866 if ((*p)->GetMessage() == message && (*p)->GetParam() == wParam) {
853867 bFind = true;
@@ -889,12 +903,15 @@ void COverlappedWindow::AddEvent(int message, WPARAM wParam, LPARAM lParam)
889903
890904 // イベントの積み上げ
891905 EnterCriticalSection(&m_objEventDataProtection);
892- CComObject<CEvent>* pEvent;
893- if (pEvent->CreateInstance(&pEvent) == S_OK) {
906+ CComObject<CEvent>* pEvent = NULL;
907+ HRESULT hr;
908+ if (SUCCEEDED(hr = CComObject<CEvent>::CreateInstance(&pEvent))) {
894909 pEvent->AddRef();
895910 pEvent->SetData(message, wParam, lParam, pt, lp);
896911 m_lstEvent.push_back(pEvent);
897912 }
913+ ATLASSERT(SUCCEEDED(hr));
914+
898915 LeaveCriticalSection(&m_objEventDataProtection);
899916
900917 // イベントハンドルをシグナルにする
@@ -944,7 +961,7 @@ STDMETHODIMP COverlappedWindow::Open(VARIANT caption, VARIANT* pvarUnk)
944961 STDMETHODIMP COverlappedWindow::Close()
945962 {
946963 // チャイルドを持っている場合は、チャイルドもクローズする
947- list<CComObject<COverlappedWindow>*>::iterator pWnd = m_lstChild.begin();
964+ std::list<CComObject<COverlappedWindow>*>::iterator pWnd = m_lstChild.begin();
948965 while (pWnd != m_lstChild.end()) {
949966 (*pWnd)->Close();
950967 pWnd++;
@@ -1310,24 +1327,27 @@ STDMETHODIMP COverlappedWindow::SetMenu(VARIANT fmt)
13101327 while (*p && *p != ',' && *p != '/' && *p != ':') {
13111328 p = CharNext(p);
13121329 }
1330+
13131331 ZeroMemory(menuname, MAX_PATH);
13141332 int menunameLen = p - st;
13151333 if (menunameLen > 0) {
13161334 _tcsncpy_s(menuname, MAX_PATH, st, menunameLen);
13171335 }
1336+
13181337 // コマンドセパレーターを検査する
13191338 CComBSTR eventname;
13201339 LPTSTR findcmd = _tcschr(menuname, _TEXT('@'));
13211340 if (findcmd) {
13221341 *findcmd = 0;
13231342 eventname = findcmd + 1;
1324- }
1325- else {
1343+
1344+ } else {
13261345 TCHAR tmp[64];
13271346 wsprintf(tmp, _TEXT("OnMenu%d"), lv1 * 100 + cmd);
13281347 eventname = tmp;
13291348 }
1330- m_cMenuMap.insert(std::pair<int, CComBSTR>(lv1 * 100 + cmd, eventname));
1349+ m_cMenuMap.insert(std::make_pair(lv1 * 100 + cmd, eventname));
1350+
13311351 // メニューの作成
13321352 MENUITEMINFO inf = {0};
13331353 inf.cbSize = sizeof(MENUITEMINFO);
@@ -1338,11 +1358,12 @@ STDMETHODIMP COverlappedWindow::SetMenu(VARIANT fmt)
13381358 InsertMenuItem(hPopupMenu, lv2, true, &inf);
13391359 lv2++;
13401360 cmd++;
1361+
13411362 // セパレーターの指定か?
13421363 if (*p == ',') {
13431364 p++;
1344- }
1345- else if (*p == ':') {
1365+
1366+ } else if (*p == ':') {
13461367 MENUITEMINFO inf = {0};
13471368 inf.cbSize = sizeof(MENUITEMINFO);
13481369 inf.fMask = MIIM_TYPE;
@@ -1412,22 +1433,25 @@ STDMETHODIMP COverlappedWindow::TrackPopupMenu(VARIANT text, VARIANT cmd, VARIAN
14121433 inf.cbSize = sizeof(MENUITEMINFO);
14131434 inf.fMask = MIIM_TYPE | MIIM_ID;
14141435 inf.fType = MFT_STRING;
1436+
14151437 if (nCommand != 0) {
14161438 inf.wID = nCommand + cmd;
1417- }
1418- else {
1439+
1440+ } else {
14191441 // コマンドベースが0ならばコマンドイベントは発生させない。
14201442 // TrackPopupMenuはコマンドを選択しなかった場合は0を返すため、0よりも大きな値にする必要がある。
14211443 inf.wID = nCommand + cmd + 1;
14221444 }
1445+
14231446 inf.dwTypeData = menuname;
14241447 InsertMenuItem(hPopupMenu, lv, true, &inf);
14251448 lv++;
14261449 cmd++;
1450+
14271451 if (*p == ',' || *p == '/') {
14281452 p++;
1429- }
1430- else if (*p == ':') {
1453+
1454+ } else if (*p == ':') {
14311455 inf.fMask = MIIM_TYPE;
14321456 inf.fType = MFT_SEPARATOR;
14331457 InsertMenuItem(hPopupMenu, lv, true, &inf);
@@ -1446,6 +1470,7 @@ STDMETHODIMP COverlappedWindow::TrackPopupMenu(VARIANT text, VARIANT cmd, VARIAN
14461470 HIWORD(pos),
14471471 m_hPopupWnd,
14481472 NULL);
1473+
14491474 DestroyMenu(hPopupMenu);
14501475 }
14511476 varRet.Detach(pRet);
@@ -1460,28 +1485,43 @@ STDMETHODIMP COverlappedWindow::get_HWND(long *pVal)
14601485
14611486 STDMETHODIMP COverlappedWindow::GetSysColor(VARIANT typ, VARIANT *col)
14621487 {
1488+ if (!col) {
1489+ return E_POINTER;
1490+ }
1491+ VariantInit(col);
1492+
14631493 // システムカラーの取得
1494+ HRESULT hr;
1495+
14641496 CComVariant varType;
1497+ if (FAILED(hr = varType.ChangeType(VT_I2, &typ))) {
1498+ return hr;
1499+ }
1500+
14651501 CComVariant varRet;
1466- varType.ChangeType(VT_I2, &typ);
14671502 varRet = (long)::GetSysColor(varType.iVal);
1468- varRet.Detach(col);
1469- return S_OK;
1503+ return varRet.Detach(col);
14701504 }
14711505
14721506 STDMETHODIMP COverlappedWindow::SetTimer(VARIANT tim, BOOL* pVal)
14731507 {
1508+ if (!pVal) {
1509+ return E_POINTER;
1510+ }
1511+
14741512 SafeCreateWnd();
14751513
1476- CComVariant varTim;
14771514 long timer = 0;
1478- if (varTim.ChangeType(VT_I4, &tim) == S_OK) {
1515+
1516+ CComVariant varTim;
1517+ if (SUCCEEDED(varTim.ChangeType(VT_I4, &tim))) {
14791518 timer = varTim.lVal;
14801519 }
1520+
14811521 if (timer) {
14821522 *pVal = ::SetTimer(m_hPopupWnd, 1, timer, NULL) ? VB_TRUE : VB_FALSE;
1483- }
1484- else {
1523+
1524+ } else {
14851525 *pVal = ::KillTimer(m_hPopupWnd, 1) ? VB_TRUE : VB_FALSE;
14861526 }
14871527 return S_OK;
@@ -1494,15 +1534,19 @@ STDMETHODIMP COverlappedWindow::CheckMenu(VARIANT cmd, VARIANT mode)
14941534 if (!m_hMenu) {
14951535 return Error(IDS_ERR_NOCREATEMENU);
14961536 }
1537+
14971538 int nCmd = 0;
1498- int nMode = 0;
1499- CComVariant varCmd, varMode;
1500- if (varCmd.ChangeType(VT_I2, &cmd) == S_OK) {
1539+ CComVariant varCmd;
1540+ if (SUCCEEDED(varCmd.ChangeType(VT_I2, &cmd))) {
15011541 nCmd = varCmd.iVal;
15021542 }
1503- if (varMode.ChangeType(VT_I2, &mode) == S_OK) {
1543+
1544+ int nMode = 0;
1545+ CComVariant varMode;
1546+ if (SUCCEEDED(varMode.ChangeType(VT_I2, &mode))) {
15041547 nMode = varMode.iVal;
15051548 }
1549+
15061550 if (nCmd >= 100) {
15071551 // メニューコマンドは100以上であるので。
15081552 MENUITEMINFO inf = {0};
@@ -1511,6 +1555,7 @@ STDMETHODIMP COverlappedWindow::CheckMenu(VARIANT cmd, VARIANT mode)
15111555 inf.fState = nMode ? MFS_CHECKED : MFS_UNCHECKED;
15121556 ::SetMenuItemInfo(m_hMenu, nCmd, false, &inf);
15131557 }
1558+
15141559 return S_OK;
15151560 }
15161561
@@ -1520,15 +1565,19 @@ STDMETHODIMP COverlappedWindow::EnableMenu(VARIANT cmd, VARIANT mode)
15201565 if (!m_hMenu) {
15211566 return Error(IDS_ERR_NOCREATEMENU);
15221567 }
1568+
15231569 int nCmd = 0;
1524- int nMode = 0;
1525- CComVariant varCmd, varMode;
1526- if (varCmd.ChangeType(VT_I2, &cmd) == S_OK) {
1570+ CComVariant varCmd;
1571+ if (SUCCEEDED(varCmd.ChangeType(VT_I2, &cmd))) {
15271572 nCmd = varCmd.iVal;
15281573 }
1529- if (varMode.ChangeType(VT_I2, &mode) == S_OK) {
1574+
1575+ int nMode = 0;
1576+ CComVariant varMode;
1577+ if (SUCCEEDED(varMode.ChangeType(VT_I2, &mode))) {
15301578 nMode = varMode.iVal;
15311579 }
1580+
15321581 if (nCmd >= 100) {
15331582 // メニューコマンドは100以上であるので。
15341583 MENUITEMINFO inf = {0};
@@ -1542,8 +1591,13 @@ STDMETHODIMP COverlappedWindow::EnableMenu(VARIANT cmd, VARIANT mode)
15421591
15431592 STDMETHODIMP COverlappedWindow::get_CreateNoCloseWindow(BOOL *pVal)
15441593 {
1594+ if (!pVal) {
1595+ return E_POINTER;
1596+ }
1597+
15451598 // クローズ禁止ウィンドウ?
15461599 *pVal = windowParam.noclose ? VB_TRUE : VB_FALSE;
1600+
15471601 return S_OK;
15481602 }
15491603
@@ -1559,40 +1613,67 @@ STDMETHODIMP COverlappedWindow::put_CreateNoCloseWindow(BOOL newVal)
15591613
15601614 STDMETHODIMP COverlappedWindow::get_Canvas(VARIANT *pVal)
15611615 {
1616+ if (!pVal) {
1617+ return E_POINTER;
1618+ }
1619+
15621620 // ドローイングインターフェイスを渡す
15631621 ::VariantInit(pVal);
1564- IUnknown* pUnk = NULL;
1565- if (m_pCanvas &&
1566- m_pCanvas->QueryInterface(IID_IUnknown, (void**)&pUnk) == S_OK) {
1622+
1623+ if (m_pCanvas) {
1624+ HRESULT hr;
1625+ CComPtr<IUnknown> pUnk;
1626+ if (FAILED(hr = m_pCanvas->QueryInterface(&pUnk))) {
1627+ return hr;
1628+ }
15671629 pVal->vt = VT_UNKNOWN;
1568- pVal->punkVal = pUnk;
1630+ pVal->punkVal = pUnk.Detach();
15691631 }
1632+
15701633 return S_OK;
15711634 }
15721635
15731636 STDMETHODIMP COverlappedWindow::get_Event(VARIANT *pVal)
15741637 {
1638+ if (!pVal) {
1639+ return E_POINTER;
1640+ }
1641+
15751642 ::VariantInit(pVal);
1643+
15761644 if (m_pEvent) {
15771645 // イベントインターフェイスの取得
1578- IUnknown* pUnk = NULL;
1579- if (m_pEvent->QueryInterface(IID_IUnknown, (void**)&pUnk) == S_OK) {
1580- pVal->vt = VT_UNKNOWN;
1581- pVal->punkVal = pUnk;
1646+ HRESULT hr;
1647+ CComPtr<IUnknown> pUnk;
1648+ if (FAILED(hr = m_pEvent->QueryInterface(&pUnk))) {
1649+ return hr;
15821650 }
1651+ pVal->vt = VT_UNKNOWN;
1652+ pVal->punkVal = pUnk.Detach();
15831653 }
1654+
15841655 return S_OK;
15851656 }
15861657
15871658 STDMETHODIMP COverlappedWindow::get_DropFiles(VARIANT *pVal)
15881659 {
1660+ if (!pVal) {
1661+ return E_POINTER;
1662+ }
1663+
15891664 m_dropfiles.GetPathArray(pVal);
1665+
15901666 return S_OK;
15911667 }
15921668
15931669 STDMETHODIMP COverlappedWindow::get_Quit(BOOL *pVal)
15941670 {
1671+ if (!pVal) {
1672+ return E_POINTER;
1673+ }
1674+
15951675 *pVal = m_bQuit ? VB_TRUE : VB_FALSE;
1676+
15961677 return S_OK;
15971678 }
15981679
@@ -1608,24 +1689,37 @@ STDMETHODIMP COverlappedWindow::put_Quit(BOOL newVal)
16081689
16091690 STDMETHODIMP COverlappedWindow::get_Form(VARIANT *pVal)
16101691 {
1692+ if (!pVal) {
1693+ return E_POINTER;
1694+ }
1695+
16111696 // フォームの公開
16121697 ::VariantInit(pVal);
1698+
16131699 if (m_pForm) {
1614- IUnknown* pUnk = NULL;
1615- if (m_pForm->QueryInterface(IID_IUnknown, (void**)&pUnk) == S_OK) {
1616- pVal->vt = VT_UNKNOWN;
1617- pVal->punkVal = pUnk;
1700+ HRESULT hr;
1701+ CComPtr<IUnknown> pUnk;
1702+ if (FAILED(hr = m_pForm->QueryInterface(&pUnk))) {
1703+ return hr;
16181704 }
1705+ pVal->vt = VT_UNKNOWN;
1706+ pVal->punkVal = pUnk.Detach();
16191707 }
16201708 return S_OK;
16211709 }
16221710
16231711 STDMETHODIMP COverlappedWindow::get_Style(long *pVal)
16241712 {
1713+ if (!pVal) {
1714+ return E_POINTER;
1715+ }
1716+
16251717 if (m_hPopupWnd) {
16261718 windowParam.style = ::GetWindowLong(m_hPopupWnd, GWL_STYLE);
16271719 }
1720+
16281721 *pVal = (long)windowParam.style;
1722+
16291723 return S_OK;
16301724 }
16311725
@@ -1658,6 +1752,10 @@ STDMETHODIMP COverlappedWindow::put_Exstyle(long newVal)
16581752
16591753 STDMETHODIMP COverlappedWindow::get_WindowClassName(BSTR *pVal)
16601754 {
1755+ if (!pVal) {
1756+ return E_POINTER;
1757+ }
1758+
16611759 CComBSTR tmp(windowParam.szClassName);
16621760 *pVal = tmp.Detach();
16631761 return S_OK;
@@ -1720,13 +1818,17 @@ STDMETHODIMP COverlappedWindow::SetPlacement(VARIANT x, VARIANT y, VARIANT w, VA
17201818
17211819 void COverlappedWindow::CreateThisInterface(VARIANT* pvarUnk)
17221820 {
1821+ ATLASSERT(pvarUnk != NULL);
1822+
17231823 // このインターフェイスを返す
17241824 ::VariantInit(pvarUnk);
1725- IUnknown* pUnk = NULL;
1726- if (QueryInterface(IID_IUnknown, (void**)&pUnk) == S_OK) {
1727- pvarUnk->vt = VT_UNKNOWN;
1728- pvarUnk->punkVal = pUnk;
1729- }
1825+
1826+ CComPtr<IUnknown> pUnk;
1827+ HRESULT hr = QueryInterface(IID_IUnknown, (void**)&pUnk);
1828+ ATLASSERT(SUCCEEDED(hr));
1829+
1830+ pvarUnk->vt = VT_UNKNOWN;
1831+ pvarUnk->punkVal = pUnk.Detach();
17301832 }
17311833
17321834 STDMETHODIMP COverlappedWindow::SetWindowStyle(VARIANT frametype, VARIANT caption_system, VARIANT maxmin, VARIANT *pvarUnk)
@@ -1754,12 +1856,10 @@ STDMETHODIMP COverlappedWindow::SetWindowStyle(VARIANT frametype, VARIANT captio
17541856 return S_OK;
17551857 }
17561858
1757-STDMETHODIMP COverlappedWindow::CreateChild(VARIANT *pvarUnk)
1859+void COverlappedWindow::PurgeUnusedWindows()
17581860 {
1759- SafeCreateWnd();
1760- ::VariantInit(pvarUnk);
17611861 // 参照カウントが1つしかないウィンドウの破棄を行う
1762- list<CComObject<COverlappedWindow>*>::iterator p = m_lstChild.begin();
1862+ std::list<CComObject<COverlappedWindow>*>::iterator p = m_lstChild.begin();
17631863 while (p != m_lstChild.end()) {
17641864 DWORD refCount = (*p)->m_dwRef;
17651865 if ((*p)->m_dwRef == 1) {
@@ -1775,20 +1875,45 @@ STDMETHODIMP COverlappedWindow::CreateChild(VARIANT *pvarUnk)
17751875 }
17761876 p++;
17771877 }
1778- //
1878+}
1879+
1880+
1881+STDMETHODIMP COverlappedWindow::CreateChild(VARIANT *pvarUnk)
1882+{
1883+ if (!pvarUnk) {
1884+ return E_POINTER;
1885+ }
1886+
1887+ SafeCreateWnd();
1888+ ::VariantInit(pvarUnk);
1889+
1890+ // 未使用のウィンドウを削除する
1891+ PurgeUnusedWindows();
1892+
1893+ // オブジェクトの作成
17791894 CComObject<COverlappedWindow>* pChild = NULL;
1780- if (pChild->CreateInstance(&pChild) == S_OK) {
1781- pChild->AddRef();
1782- pChild->SetParent(m_hPopupWnd);
1783- pChild->put_WaitCursor(m_dWaitCursor);
1784- m_lstChild.push_back(pChild);
1785- // インターフェイスを返す
1786- IUnknown* pUnk = NULL;
1787- if (pChild->QueryInterface(IID_IUnknown, (void**)&pUnk) == S_OK) {
1788- pvarUnk->vt = VT_UNKNOWN;
1789- pvarUnk->punkVal = pUnk;
1790- }
1895+ HRESULT hr;
1896+ if (FAILED(hr = CComObject<COverlappedWindow>::CreateInstance(&pChild))) {
1897+ return hr;
17911898 }
1899+
1900+ // 返却用インターフェイスの取得
1901+ CComPtr<IUnknown> pUnk;
1902+ if (FAILED(hr = pChild->QueryInterface(&pUnk))) {
1903+ delete pChild;
1904+ return hr;
1905+ }
1906+
1907+ pChild->SetParent(m_hPopupWnd);
1908+ pChild->put_WaitCursor(m_dWaitCursor);
1909+
1910+ // リストに保存するため参照カウント+1する.
1911+ pChild->AddRef();
1912+ m_lstChild.push_back(pChild);
1913+
1914+ // インターフェイスを返す
1915+ pvarUnk->vt = VT_UNKNOWN;
1916+ pvarUnk->punkVal = pUnk.Detach();
17921917 return S_OK;
17931918 }
17941919
@@ -1811,7 +1936,7 @@ void COverlappedWindow::SetWaitParam(int *count, HWND *hWnd, HANDLE *hEvent)
18111936 hWnd[*count] = m_hPopupWnd;
18121937 (*count)++;
18131938 // チャイルドを登録
1814- list<CComObject<COverlappedWindow>*>::iterator p = m_lstChild.begin();
1939+ std::list<CComObject<COverlappedWindow>*>::iterator p = m_lstChild.begin();
18151940 while ((p != m_lstChild.end()) && (*count < MAXIMUM_WAIT_OBJECTS)) {
18161941 // チャイルドが所有するチャイルドを再起的に呼び出す
18171942 (*p)->SetWaitParam(count, hWnd, hEvent);
@@ -1936,7 +2061,7 @@ STDMETHODIMP COverlappedWindow::put_AutoClose(BOOL newVal)
19362061 return S_OK;
19372062 }
19382063
1939-void COverlappedWindow::CreateWindowList(list<HWND>& lstWnd, BOOL bSearchRoot)
2064+void COverlappedWindow::CreateWindowList(std::list<HWND>& lstWnd, BOOL bSearchRoot)
19402065 {
19412066 HWND* hWnds = NULL;
19422067 if (m_hParentWnd && bSearchRoot) {
@@ -1948,7 +2073,7 @@ void COverlappedWindow::CreateWindowList(list<HWND>& lstWnd, BOOL bSearchRoot)
19482073 }
19492074 else {
19502075 // ここが根元である
1951- list<CComObject<COverlappedWindow>*>::iterator p = m_lstChild.begin();
2076+ std::list<CComObject<COverlappedWindow>*>::iterator p = m_lstChild.begin();
19522077 DWORD stl = ::GetWindowLong(m_hPopupWnd, GWL_STYLE);
19532078 if (stl & WS_VISIBLE) {
19542079 // 表示されているウィンドウのみを登録する
@@ -1969,11 +2094,11 @@ void COverlappedWindow::CreateWindowList(list<HWND>& lstWnd, BOOL bSearchRoot)
19692094 void COverlappedWindow::MoveNextOverlapped()
19702095 {
19712096 // 順序リストの生成を依頼する
1972- list<HWND>lstWnd;
2097+ std::list<HWND>lstWnd;
19732098 CreateWindowList(lstWnd, true);
19742099 // 現在位置を把握する
19752100 HWND hActiveWnd = ::GetActiveWindow();
1976- list<HWND>::iterator p = lstWnd.begin();
2101+ std::list<HWND>::iterator p = lstWnd.begin();
19772102 while (p != lstWnd.end()) {
19782103 // 列挙
19792104 if (hActiveWnd == *p) {
@@ -2026,7 +2151,7 @@ STDMETHODIMP COverlappedWindow::put_WaitCursor(short newVal)
20262151 ::SendMessage(m_hPopupWnd, WM_SETCURSOR, (WPARAM)m_hPopupWnd, 0);
20272152 }
20282153 // チャイルドを持っている場合は、チャイルドにもウェイトカーソルを適用する
2029- list<CComObject<COverlappedWindow>*>::iterator pWnd = m_lstChild.begin();
2154+ std::list<CComObject<COverlappedWindow>*>::iterator pWnd = m_lstChild.begin();
20302155 while (pWnd != m_lstChild.end()) {
20312156 (*pWnd)->put_WaitCursor(newVal);
20322157 pWnd++;
@@ -2064,14 +2189,15 @@ STDMETHODIMP COverlappedWindow::CenterWindow()
20642189 if (m_hParentWnd) {
20652190 // 親ウィンドウがあれば、その中央に位置あわせする
20662191 ::GetWindowRect(m_hParentWnd, &rct);
2067- }
2068- else {
2192+
2193+ } else {
20692194 HWND hwnd = ::GetDesktopWindow();
20702195 if (!hwnd) {
20712196 return S_OK;
20722197 }
20732198 ::GetWindowRect(hwnd, &rct);
20742199 }
2200+
20752201 int x = rct.left + (rct.right - rct.left) / 2 - windowParam.width / 2;
20762202 int y = rct.top + (rct.bottom - rct.top) / 2 - windowParam.height / 2;
20772203 WINDOWPLACEMENT pls = {0};
@@ -2081,16 +2207,20 @@ STDMETHODIMP COverlappedWindow::CenterWindow()
20812207 pls.rcNormalPosition.bottom = y + windowParam.height;
20822208 pls.rcNormalPosition.right = x + windowParam.width;
20832209 ::SetWindowPlacement(m_hPopupWnd, &pls);
2210+
20842211 return S_OK;
20852212 }
20862213
20872214 STDMETHODIMP COverlappedWindow::get_ClassObject(VARIANT* pVal)
20882215 {
2216+ if (!pVal) {
2217+ return E_POINTER;
2218+ }
2219+
20892220 ::VariantInit(pVal);
20902221 if (m_pClassDisp) {
2091- m_pClassDisp->AddRef();
2092- pVal->pdispVal = m_pClassDisp;
2093- pVal->vt = VT_UNKNOWN;
2222+ CComVariant tmp(m_pClassDisp);
2223+ return tmp.Detach(pVal);
20942224 }
20952225 return S_OK;
20962226 }
@@ -2099,7 +2229,9 @@ STDMETHODIMP COverlappedWindow::put_ClassObject(VARIANT newVal)
20992229 {
21002230 if (m_pClassDisp) {
21012231 m_pClassDisp->Release();
2232+ m_pClassDisp = NULL;
21022233 }
2234+
21032235 if (newVal.vt == VT_DISPATCH) {
21042236 m_pClassDisp = newVal.pdispVal;
21052237 m_pClassDisp->AddRef();
@@ -2160,6 +2292,10 @@ STDMETHODIMP COverlappedWindow::get_innerWidth(double *pVal)
21602292
21612293 STDMETHODIMP COverlappedWindow::get_innerHeight(double *pVal)
21622294 {
2295+ if (!pVal) {
2296+ return E_POINTER;
2297+ }
2298+
21632299 SafeCreateWnd();
21642300 RECT rct;
21652301 ::GetClientRect(m_hPopupWnd, &rct);
@@ -2170,13 +2306,20 @@ STDMETHODIMP COverlappedWindow::get_innerHeight(double *pVal)
21702306 ::DPtoLP(hdc, &pt, 1);
21712307 ::SetMapMode(hdc, md);
21722308 ::ReleaseDC(m_hPopupWnd, hdc);
2309+
21732310 *pVal = pt.y / 10.;
2311+
21742312 return S_OK;
21752313 }
21762314
21772315 STDMETHODIMP COverlappedWindow::get_AutoReleaseClassObject(BOOL *pVal)
21782316 {
2317+ if (!pVal) {
2318+ return E_POINTER;
2319+ }
2320+
21792321 *pVal = m_bAutoReleaseClassObject ? VB_TRUE : VB_FALSE;
2322+
21802323 return S_OK;
21812324 }
21822325
@@ -2188,7 +2331,12 @@ STDMETHODIMP COverlappedWindow::put_AutoReleaseClassObject(BOOL newVal)
21882331
21892332 STDMETHODIMP COverlappedWindow::get_DefaultAction(BOOL *pVal)
21902333 {
2334+ if (!pVal) {
2335+ return E_POINTER;
2336+ }
2337+
21912338 *pVal = m_bDefaultAction ? VB_TRUE : VB_FALSE;
2339+
21922340 return S_OK;
21932341 }
21942342
@@ -2225,7 +2373,7 @@ STDMETHODIMP COverlappedWindow::GetClipboardText(VARIANT *pVarText)
22252373 // UNICODE文字列があれば、そちらを優先して取得する
22262374 HGLOBAL hGlobal = ::GetClipboardData(CF_UNICODETEXT);
22272375 if (hGlobal) {
2228- LPWSTR p = (LPWSTR)GlobalLock(hGlobal);
2376+ LPCWSTR p = (LPCWSTR)GlobalLock(hGlobal);
22292377 if (p) {
22302378 CComBSTR wstr(p);
22312379 GlobalUnlock(hGlobal);
@@ -2233,12 +2381,12 @@ STDMETHODIMP COverlappedWindow::GetClipboardText(VARIANT *pVarText)
22332381 pVarText->vt = VT_BSTR;
22342382 }
22352383 }
2236- }
2237- else if (IsClipboardFormatAvailable(CF_TEXT)) {
2384+
2385+ } else if (IsClipboardFormatAvailable(CF_TEXT)) {
22382386 // UNICODE文字列がない場合
22392387 HGLOBAL hGlobal = ::GetClipboardData(CF_TEXT);
22402388 if (hGlobal) {
2241- LPCSTR p = (LPSTR)GlobalLock(hGlobal);
2389+ LPCSTR p = (LPCSTR)GlobalLock(hGlobal);
22422390 if (p) {
22432391 CComBSTR wstr(p);
22442392 GlobalUnlock(hGlobal);
--- a/OverlappedWindow.h
+++ b/OverlappedWindow.h
@@ -34,9 +34,9 @@ public:
3434 }
3535 void Clear()
3636 {
37- list<LPTSTR>::iterator p = m_lstPath.begin();
37+ std::list<LPTSTR>::iterator p = m_lstPath.begin();
3838 while (p != m_lstPath.end()) {
39- delete[] * p;
39+ delete[] *p;
4040 p = m_lstPath.erase(p);
4141 }
4242 }
@@ -44,8 +44,7 @@ public:
4444 {
4545 Clear();
4646 int count = ::DragQueryFile(hDrop, -1, NULL, 0);
47- int i;
48- for (i = 0; i < count; i++) {
47+ for (int i = 0; i < count; i++) {
4948 DWORD sz = ::DragQueryFile(hDrop, i, NULL, 0);
5049 LPTSTR pBuf = new TCHAR[sz + 1];
5150 ::DragQueryFile(hDrop, i, pBuf, MAX_PATH);
@@ -63,7 +62,7 @@ public:
6362 VARIANT* pvars;
6463 if (SafeArrayAccessData(pArray, (void**)&pvars) == S_OK) {
6564 int i = 0;
66- list<LPTSTR>::iterator p = m_lstPath.begin();
65+ std::list<LPTSTR>::iterator p = m_lstPath.begin();
6766 while (p != m_lstPath.end()) {
6867 CComVariant wbuf(*p);
6968 wbuf.Detach(&pvars[i]);
@@ -76,8 +75,9 @@ public:
7675 pvarPathName->vt = VT_ARRAY | VT_VARIANT;
7776 pvarPathName->parray = pArray;
7877 }
78+
7979 protected:
80- list<LPTSTR> m_lstPath;
80+ std::list<LPTSTR> m_lstPath;
8181 };
8282
8383 /////////////////////////////////////////////////////////////////////////////
@@ -164,7 +164,7 @@ class ATL_NO_VTABLE COverlappedWindow :
164164 public CProxy_IOverlappedWindowEvents< COverlappedWindow >
165165 {
166166 public:
167- COverlappedWindow();
167+ COverlappedWindow() {};
168168
169169 DECLARE_GET_CONTROLLING_UNKNOWN()
170170 DECLARE_REGISTRY_RESOURCEID(IDR_OVERLAPPEDWINDOW)
@@ -231,6 +231,21 @@ public:
231231 protected:
232232 HRESULT ClassObjectInvoke(LPCWSTR handler);
233233
234+public:
235+ ULONG InternalAddRef()
236+ {
237+ ULONG ref = CComObjectRootEx<CComSingleThreadModel>::InternalAddRef();
238+ ATLTRACE(_TEXT("*addref=%d\n"), ref);
239+ return ref;
240+ }
241+
242+ ULONG InternalRelease()
243+ {
244+ ULONG ref = CComObjectRootEx<CComSingleThreadModel>::InternalRelease();
245+ ATLTRACE(_TEXT("*release=%d\n"), ref);
246+ return ref;
247+ }
248+
234249 // IOverlappedWindow
235250 public:
236251 STDMETHOD(GetClipboardText)(/*[out]*/VARIANT* pVarText);
@@ -253,7 +268,7 @@ public:
253268 STDMETHOD(put_ExitCode)(/*[in]*/ short newVal);
254269 STDMETHOD(get_Object)(/*[in,optional]*/VARIANT idx, /*[out, retval]*/ VARIANT *pVal);
255270 void MoveNextOverlapped();
256- void CreateWindowList(list<HWND>& lstWnd, BOOL bSearchRoot);
271+ void CreateWindowList(std::list<HWND>& lstWnd, BOOL bSearchRoot);
257272 STDMETHOD(get_AutoClose)(/*[out, retval]*/ BOOL *pVal);
258273 STDMETHOD(put_AutoClose)(/*[in]*/ BOOL newVal);
259274 STDMETHOD(DoModal)(/*[out,retval]*/VARIANT* retcode);
@@ -346,19 +361,22 @@ protected:
346361 CComObject<CForm>* m_pForm;
347362 CComObject<CEvent>* m_pEvent;
348363 CComObject<CObjectMap>* m_pObject;
349- list<CComObject<CEvent>*> m_lstEvent;
350- list<CComObject<COverlappedWindow>*> m_lstChild;
351- vector<CComVariant> m_vectorObject;
364+ std::list<CComObject<CEvent>*> m_lstEvent;
365+ std::list<CComObject<COverlappedWindow>*> m_lstChild;
366+ std::vector<CComVariant> m_vectorObject;
352367 dropfiledata m_dropfiles;
353368 CRITICAL_SECTION m_objEventDataProtection;
354369 BOOL m_bAutoReleaseClassObject;
355370 BOOL m_bDefaultAction;
371+
356372 protected:
357373 static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
358374 void AddEvent(int message, WPARAM wParam, LPARAM lParam);
359375 void AddEventSingle(int message, WPARAM wParam, LPARAM lParam);
360376 void CreateThisInterface(VARIANT* pvarUnk);
361377 void SetTitle();
378+ void PurgeUnusedWindows();
379+
362380 protected:
363381 IDispatch* m_pClassDisp;
364382 int m_dWaitCursor;
@@ -373,5 +391,5 @@ protected:
373391 HWND m_hPopupWnd;
374392 HWND m_hParentWnd;
375393 HICON m_hIcon;
376- map<int, CComBSTR> m_cMenuMap;
394+ std::map<int, CComBSTR> m_cMenuMap;
377395 };
--- a/PrivateProfile.cpp
+++ b/PrivateProfile.cpp
@@ -39,16 +39,17 @@ STDMETHODIMP CPrivateProfile::OpenSection(VARIANT text, VARIANT* pVal)
3939 }
4040 ATLASSERT(pSection);
4141
42- pSection->m_szProfilePath = m_bstr_profilepath;
43- pSection->m_szSectionName = varText.bstrVal;
44-
45- IUnknown* pUnk = NULL;
46- if (FAILED(hr = pSection->QueryInterface(IID_IUnknown, (void**)&pUnk))) {
42+ CComPtr<IUnknown> pUnk = NULL;
43+ if (FAILED(hr = pSection->QueryInterface(&pUnk))) {
44+ delete pSection;
4745 return hr;
4846 }
4947 ATLASSERT(pUnk);
5048
49+ pSection->m_szProfilePath = m_bstr_profilepath;
50+ pSection->m_szSectionName = varText.bstrVal;
51+
5152 pVal->vt = VT_UNKNOWN;
52- pVal->punkVal = pUnk;
53+ pVal->punkVal = pUnk.Detach();
5354 return S_OK;
5455 }
--- a/SeraphyScriptTools.cpp
+++ b/SeraphyScriptTools.cpp
@@ -61,9 +61,22 @@ BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
6161 //
6262 _Module.Init(ObjectMap, hInstance, &LIBID_SERAPHYSCRIPTTOOLSLib);
6363 DisableThreadLibraryCalls(hInstance);
64- }
65- else if (dwReason == DLL_PROCESS_DETACH)
64+
65+#ifdef _DEBUG
66+ //_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
67+ //_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
68+ _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_EVERY_128_DF);
69+ //_CrtSetBreakAlloc(898);
70+#endif
71+
72+ } else if (dwReason == DLL_PROCESS_DETACH) {
6673 _Module.Term();
74+
75+#ifdef _DEBUG
76+ _CrtDumpMemoryLeaks();
77+#endif
78+ }
79+
6780 return TRUE; // ok
6881 }
6982
--- a/SeraphyScriptTools.h
+++ b/SeraphyScriptTools.h
@@ -4,7 +4,7 @@
44
55
66 /* File created by MIDL compiler version 8.00.0603 */
7-/* at Sun Aug 16 18:41:49 2015
7+/* at Tue Aug 18 01:30:13 2015
88 */
99 /* Compiler settings for SeraphyScriptTools.idl:
1010 Oicf, W1, Zp8, env=Win64 (32b run), target_arch=AMD64 8.00.0603
--- a/Shell.cpp
+++ b/Shell.cpp
@@ -1,11 +1,12 @@
11 // Shell.cpp : CShell のインプリメンテーション
22 #include "stdafx.h"
3+
34 #include "SeraphyScriptTools.h"
45 #include "Shell.h"
56 #include "generic.h"
7+
68 #include <list>
79 #include <vector>
8-using namespace std;
910
1011 #pragma comment(lib, "Version.lib")
1112
@@ -71,14 +72,20 @@ STDMETHODIMP CShell::ShellExecute(VARIANT path, VARIANT param, VARIANT initdir,
7172 info.nShow = nShow;
7273 if (ShellExecuteEx(&info)) {
7374 // ShellExecObjの生成
75+ HRESULT hr;
7476 CComObject<CShellExecObj>* pExec = NULL;
75- if (pExec->CreateInstance(&pExec) == S_OK) {
76- pExec->m_hProcess = info.hProcess;
77- IUnknown* pUnk = NULL;
78- pExec->QueryInterface(IID_IUnknown, (void**)&pUnk);
79- punkVal->vt = VT_UNKNOWN;
80- punkVal->punkVal = pUnk;
77+ if (FAILED(hr = CComObject<CShellExecObj>::CreateInstance(&pExec))) {
78+ return hr;
79+ }
80+ pExec->m_hProcess = info.hProcess;
81+
82+ IUnknown* pUnk = NULL;
83+ if (FAILED(hr = pExec->QueryInterface(&pUnk))) {
84+ delete pExec;
85+ return hr;
8186 }
87+ punkVal->vt = VT_UNKNOWN;
88+ punkVal->punkVal = pUnk;
8289 }
8390 return S_OK;
8491 }
@@ -321,38 +328,45 @@ STDMETHODIMP CShell::ParseName(VARIANT text, VARIANT *pVal)
321328 {
322329 ::VariantInit(pVal);
323330
331+ HRESULT hr;
324332 CComVariant varText;
325- if (varText.ChangeType(VT_BSTR, &text) == S_OK) {
326- CComObject<CParseName>* pParse = NULL;
327- if (pParse->CreateInstance(&pParse) == S_OK) {
328- pParse->m_bstr_path = (LPCWSTR)varText.bstrVal;
329- IUnknown* pUnk = NULL;
330- if (pParse->QueryInterface(IID_IUnknown, (void**)&pUnk) == S_OK) {
331- pVal->vt = VT_UNKNOWN;
332- pVal->punkVal = pUnk;
333- }
334- }
333+ if (FAILED(hr = varText.ChangeType(VT_BSTR, &text))) {
334+ return hr;
335335 }
336- return S_OK;
337-}
338336
339-/////////////////////////////////////////////////////////////////////////////
340-// CParseName
337+ // COMオブジェクトの作成
338+ CComObject<CParseName>* pParse = NULL;
339+ if (FAILED(hr = CComObject<CParseName>::CreateInstance(&pParse))) {
340+ return hr;
341+ }
341342
342-STDMETHODIMP CParseName::InterfaceSupportsErrorInfo(REFIID riid)
343-{
344- static const IID* arr[] = {
345- &IID_ISeraphyScriptTool_ParseName
346- };
343+ // COMスマートポインタに保持する.(自動リリース)
344+ CComPtr<ISeraphyScriptTool_ParseName> pIntf;
345+ if (FAILED(hr = pParse->QueryInterface(
346+ IID_ISeraphyScriptTool_ParseName, reinterpret_cast<void**>(&pIntf)))) {
347+ delete pParse;
348+ return hr;
349+ }
347350
348- for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
349- if (IsEqualGUID(*arr[i], riid)) {
350- return S_OK;
351- }
351+ // パスを設定する.
352+ if (FAILED(hr = pIntf->put_PathName(varText.bstrVal))) {
353+ return hr;
354+ }
355+
356+ // IUnknownに変換する
357+ IUnknown* pUnk = NULL;
358+ if (FAILED(hr = pIntf->QueryInterface(IID_IUnknown, (void**)&pUnk))) {
359+ return hr;
352360 }
353- return S_FALSE;
361+
362+ pVal->vt = VT_UNKNOWN;
363+ pVal->punkVal = pUnk;
364+ return S_OK;
354365 }
355366
367+/////////////////////////////////////////////////////////////////////////////
368+// CParseName
369+
356370 STDMETHODIMP CParseName::get_PathName(BSTR *pVal)
357371 {
358372 return m_bstr_path.CopyTo(pVal);
--- a/Shell.h
+++ b/Shell.h
@@ -19,18 +19,17 @@ public:
1919 {
2020 m_bConfirm = true;
2121 m_bSilent = false;
22- //
2322 m_pMainWindow = NULL;
24- m_pMalloc = NULL;
25- SHGetMalloc(&m_pMalloc);
23+ }
24+
25+ HRESULT FinalConstruct()
26+ {
27+ return SHGetMalloc(&m_pMalloc);
2628 }
2729
2830 void FinalRelease()
2931 {
30- if (m_pMalloc) {
31- m_pMalloc->Release();
32- m_pMalloc = NULL;
33- }
32+ m_pMalloc.Release();
3433 }
3534
3635 HWND GetMainWindow()
@@ -76,7 +75,7 @@ public:
7675 protected:
7776 BOOL m_bSilent;
7877 BOOL m_bConfirm;
79- IMalloc* m_pMalloc;
78+ CComPtr<IMalloc> m_pMalloc;
8079 IOverlappedWindow* m_pMainWindow;
8180
8281 HRESULT FileOperationCore(UINT wFunc, FILEOP_FLAGS flag, VARIANT* from, VARIANT* to, VARIANT* pResult);
@@ -90,7 +89,7 @@ protected:
9089 // CShellExecObj
9190 class ATL_NO_VTABLE CShellExecObj :
9291 public CComObjectRootEx<CComSingleThreadModel>,
93- // public CComCoClass<CShellExecObj, &CLSID_ShellExecObj>,
92+ public CComCoClass<CShellExecObj, &CLSID_ShellExecObj>,
9493 public IDispatchImpl<IShellExecObj, &IID_IShellExecObj, &LIBID_SERAPHYSCRIPTTOOLSLib>
9594 {
9695 public:
@@ -98,6 +97,7 @@ public:
9897 {
9998 m_hProcess = NULL;
10099 }
100+
101101 void FinalRelease()
102102 {
103103 if (m_hProcess) {
@@ -105,7 +105,8 @@ public:
105105 m_hProcess = NULL;
106106 }
107107 }
108- DECLARE_REGISTRY_RESOURCEID(IDR_SHELLEXECOBJ)
108+
109+ //DECLARE_REGISTRY_RESOURCEID(IDR_SHELLEXECOBJ)
109110
110111 DECLARE_PROTECT_FINAL_CONSTRUCT()
111112
@@ -118,7 +119,11 @@ public:
118119 public:
119120 STDMETHOD(get_ExitCode)(/*[out, retval]*/ long *pVal);
120121 STDMETHOD(Wait)(/*[in,optional]*/VARIANT tim,/*[out,retval]*/VARIANT* pVal);
122+
123+protected:
121124 HANDLE m_hProcess;
125+
126+ friend class CShell;
122127 };
123128
124129 // shell.h : CParseName の宣言
@@ -129,7 +134,7 @@ public:
129134 class ATL_NO_VTABLE CParseName :
130135 public CComObjectRootEx<CComSingleThreadModel>,
131136 public CComCoClass<CParseName, &CLSID_ParseName>,
132- public ISupportErrorInfo,
137+ public ISupportErrorInfoImpl<&IID_ISeraphyScriptTool_ParseName>,
133138 public IDispatchImpl<ISeraphyScriptTool_ParseName, &IID_ISeraphyScriptTool_ParseName, &LIBID_SERAPHYSCRIPTTOOLSLib>
134139 {
135140 public:
@@ -147,9 +152,6 @@ public:
147152 COM_INTERFACE_ENTRY(ISupportErrorInfo)
148153 END_COM_MAP()
149154
150- // ISupportsErrorInfo
151- STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
152-
153155 // ISeraphyScriptTool_ParseName
154156 public:
155157 STDMETHOD(get_Directory)(/*[out, retval]*/ BSTR *pVal);
@@ -163,5 +165,7 @@ public:
163165 STDMETHOD(put_FileName)(/*[in]*/ BSTR newVal);
164166 STDMETHOD(get_PathName)(/*[out, retval]*/ BSTR *pVal);
165167 STDMETHOD(put_PathName)(/*[in]*/ BSTR newVal);
168+
169+protected:
166170 CComBSTR m_bstr_path;
167171 };
--- a/StdAfx.cpp
+++ b/StdAfx.cpp
@@ -8,5 +8,3 @@
88 #include <statreg.h>
99 #include <statreg.cpp>
1010 #endif
11-
12-// FIXME: #include <atlimpl.cpp>
--- a/StdAfx.h
+++ b/StdAfx.h
@@ -31,6 +31,12 @@
3131 #endif
3232 #endif
3333
34+// デバッグヒープ
35+#ifdef _DEBUG
36+#define CRTDBG_MAP_ALLOC
37+#include <crtdbg.h>
38+#endif
39+
3440 #include <atlbase.h>
3541
3642 // CComModule クラスから派生したクラスを使用して、オーバーライドする場合
--- a/TreeItem.cpp
+++ b/TreeItem.cpp
@@ -3,8 +3,8 @@
33 #include "SeraphyScriptTools.h"
44 #include "TreeItem.h"
55 #include "objectmap.h"
6+
67 #include <list>
7-using namespace std;
88
99
1010 /////////////////////////////////////////////////////////////////////////////
@@ -13,7 +13,7 @@ using namespace std;
1313 BOOL CTreeItem::DeleteTreeItemWithData(HWND hWnd, HTREEITEM hItem)
1414 {
1515 HTREEITEM hRoot = hItem;
16- list<HTREEITEM> lst;
16+ std::list<HTREEITEM> lst;
1717 lst.push_back(hItem);
1818 while (!lst.empty()) {
1919 hItem = lst.front();
@@ -48,14 +48,31 @@ BOOL CTreeItem::DeleteTreeItemWithData(HWND hWnd, HTREEITEM hItem)
4848 return true;
4949 }
5050
51-void CTreeItem::CreateTreeItem(HWND hWnd, HTREEITEM hParent, LPCTSTR text, IUnknown **punkVal)
51+/**
52+ * ツリーアイテムを保持するオブジェクトを生成して返す.
53+ * IUnknownは参照カウント1に設定されているため、呼び出し側でReleaseが必要.
54+ */
55+HRESULT CTreeItem::CreateTreeItem(HWND hWnd, HTREEITEM hParent, LPCTSTR text, IUnknown **punkVal)
5256 {
57+ if (!punkVal) {
58+ return E_POINTER;
59+ }
60+ *punkVal = NULL;
61+
5362 // アイテムが保有する連想配列を生成する
54- IUnknown* pUnk = NULL;
63+
64+ HRESULT hr;
65+
5566 CComObject<CObjectMap>* pMap = NULL;
56- if (SUCCEEDED(pMap->CreateInstance(&pMap))) {
57- pMap->QueryInterface(IID_IUnknown, (void**)&pUnk);
67+ if (FAILED(hr = CComObject<CObjectMap>::CreateInstance(&pMap))) {
68+ return hr;
5869 }
70+ CComPtr<IUnknown> pMapUnk;
71+ if (FAILED(hr = pMap->QueryInterface(&pMapUnk))) {
72+ delete pMap;
73+ return hr;
74+ }
75+
5976 // 挿入するアイテムの定義
6077 ATL::CString tmp(text);
6178 TVINSERTSTRUCT is = {0};
@@ -64,21 +81,319 @@ void CTreeItem::CreateTreeItem(HWND hWnd, HTREEITEM hParent, LPCTSTR text, IUnkn
6481 is.item.mask = TVIF_TEXT | TVIF_PARAM;
6582 is.item.pszText = tmp.GetBuffer();
6683 is.item.cchTextMax = tmp.GetLength();
84+
85+ IUnknown* pUnk = NULL;
86+ if (FAILED(hr = pMapUnk.CopyTo(&pUnk))) {
87+ return hr;
88+ }
6789 is.item.lParam = (LPARAM)pUnk;
6890
6991 HTREEITEM hNewItem = TreeView_InsertItem(hWnd, &is);
70- if (hNewItem) {
71- // アイテムへのオブジェクトを作成する
72- CComObject<CTreeItem>* pItem = NULL;
73- if (SUCCEEDED(pItem->CreateInstance(&pItem))) {
74- pItem->SetParam(hWnd, hNewItem);
75- pItem->QueryInterface(IID_IUnknown, (void**)punkVal);
76- }
92+ if (!hNewItem) {
93+ // 登録されなかった場合はタグアイテムに関連づけたpUnkを解放する
94+ pUnk->Release();
95+ return E_FAIL; // 不明なエラー
96+ }
97+
98+ // アイテムへのオブジェクトを作成する
99+ CComObject<CTreeItem>* pItem = NULL;
100+ if (FAILED(hr = CComObject<CTreeItem>::CreateInstance(&pItem))) {
101+ return hr;
102+ }
103+ pItem->SetParam(hWnd, hNewItem);
104+
105+ if (FAILED(hr = pItem->QueryInterface(punkVal))) {
106+ delete pItem;
107+ return hr;
77108 }
109+ return S_OK;
78110 }
79111
80112 STDMETHODIMP CTreeItem::IsValid(BOOL *pResult)
81113 {
114+ if (!pResult) {
115+ return E_FAIL;
116+ }
117+
82118 *pResult = (m_hItem != NULL) ? VB_TRUE : VB_FALSE;
119+
120+ return S_OK;
121+}
122+
123+STDMETHODIMP CTreeItem::Sort()
124+{
125+ HRESULT ret = InitialCheck();
126+ if (ret == S_OK) {
127+ if (m_hItem) {
128+ TreeView_SortChildren(m_hWnd, m_hItem, 0);
129+ }
130+ else {
131+ // 不正なアイテムを参照している
132+ ret = DISP_E_EXCEPTION;
133+ }
134+ }
135+ return ret;
136+}
137+
138+STDMETHODIMP CTreeItem::Expand()
139+{
140+ HRESULT ret = InitialCheck();
141+ if (ret == S_OK) {
142+ if (m_hItem) {
143+ TreeView_Expand(m_hWnd, m_hItem, TVE_EXPAND);
144+ }
145+ else {
146+ // 不正なアイテムを参照している
147+ ret = DISP_E_EXCEPTION;
148+ }
149+ }
150+ return ret;
151+}
152+
153+STDMETHODIMP CTreeItem::Select()
154+{
155+ HRESULT ret = InitialCheck();
156+ if (ret == S_OK) {
157+ if (m_hItem) {
158+ TreeView_SelectItem(m_hWnd, m_hItem);
159+ }
160+ else {
161+ // 不正なアイテムを参照している
162+ ret = DISP_E_EXCEPTION;
163+ }
164+ }
165+ return ret;
166+}
167+
168+STDMETHODIMP CTreeItem::Erase()
169+{
170+ HRESULT ret = InitialCheck();
171+ if (ret == S_OK) {
172+ if (m_hItem) {
173+ if (DeleteTreeItemWithData(m_hWnd, m_hItem)) {
174+ // 削除に成功したら、このハンドルを無効にする
175+ m_hWnd = NULL;
176+ m_hItem = NULL;
177+ }
178+ }
179+ else {
180+ // 不正なアイテムを参照している
181+ ret = DISP_E_EXCEPTION;
182+ }
183+ }
184+ return ret;
185+}
186+
187+STDMETHODIMP CTreeItem::Create(/*[in]*/VARIANT text,/*[out,retval]*/IUnknown** punkVal)
188+{
189+ // アイテムの作成
190+ *punkVal = NULL;
191+ HRESULT ret = InitialCheck();
192+ if (FAILED(ret)) {
193+ return ret;
194+ }
195+
196+ if (m_hItem) {
197+ CComVariant str;
198+ ATL::CString mes(_TEXT(""));
199+ if (str.ChangeType(VT_BSTR, &text) == S_OK) {
200+ mes = str.bstrVal;
201+ }
202+ CreateTreeItem(m_hWnd, m_hItem, mes, punkVal);
203+ return S_OK;
204+ }
205+ // 不正なアイテムを参照している
206+ return DISP_E_EXCEPTION;
207+}
208+
209+STDMETHODIMP CTreeItem::get_Object(/*[in,optional]*/VARIANT idx, /*[out, retval]*/ VARIANT *pVal)
210+{
211+ // アイテムに関連付けられた連想配列オブジェクトを取得する
212+ ::VariantInit(pVal);
213+ HRESULT ret = InitialCheck();
214+ if (!m_hItem) {
215+ ret = DISP_E_EXCEPTION;
216+ }
217+ if (ret == S_OK) {
218+ TVITEM itm = {0};
219+ itm.mask = TVIF_PARAM;
220+ itm.hItem = m_hItem;
221+ if (TreeView_GetItem(m_hWnd, &itm)) {
222+ IUnknown* pUnk = (IUnknown*)itm.lParam;
223+ if (pUnk) {
224+ pUnk->AddRef();
225+ pVal->vt = VT_UNKNOWN;
226+ pVal->punkVal = pUnk;
227+ }
228+ }
229+ }
230+ return ret;
231+}
232+
233+HRESULT CTreeItem::InitialCheck()
234+{
235+ // ウィンドウが有効か検査する
236+ if (m_hWnd && ::IsWindow(m_hWnd)) {
237+ return S_OK;
238+ }
239+ return Error(IDS_ERR_TREEERROR);
240+}
241+
242+STDMETHODIMP CTreeItem::get_Text(/*[out, retval]*/ BSTR *pVal)
243+{
244+ // テキストの取得
245+ HRESULT hr;
246+ if (FAILED(hr = InitialCheck())) {
247+ return hr;
248+ }
249+ if (!m_hItem) {
250+ // 不正なアイテムを参照している
251+ return DISP_E_EXCEPTION;
252+ }
253+
254+ TCHAR text[MAX_PATH] = {0};
255+ TVITEM itm = {0};
256+ itm.mask = TVIF_TEXT;
257+ itm.hItem = m_hItem;
258+ itm.pszText = text;
259+ itm.cchTextMax = MAX_PATH;
260+ if (TreeView_GetItem(m_hWnd, &itm)) {
261+ CComBSTR ret(text);
262+ *pVal = ret.Detach();
263+ }
83264 return S_OK;
84265 }
266+
267+STDMETHODIMP CTreeItem::put_Text(/*[in]*/ BSTR newVal)
268+{
269+ // テキストの書き換え
270+ HRESULT hr;
271+ if (FAILED(hr = InitialCheck())) {
272+ return hr;
273+ }
274+ if (!m_hItem) {
275+ // 不正なアイテムを参照している
276+ return DISP_E_EXCEPTION;
277+ }
278+
279+ ATL::CString tmp(newVal);
280+ TVITEM itm = {0};
281+ itm.mask = TVIF_TEXT;
282+ itm.hItem = m_hItem;
283+ itm.pszText = tmp.GetBuffer();
284+ itm.cchTextMax = tmp.GetLength(); // Setの場合は無視される
285+ TreeView_SetItem(m_hWnd, &itm);
286+ return S_OK;
287+}
288+
289+STDMETHODIMP CTreeItem::get_PrevItem(/*[out, retval]*/ IUnknown* *pVal)
290+{
291+ // 前のアイテム
292+ *pVal = NULL;
293+
294+ HRESULT hr;
295+ if (FAILED(hr = InitialCheck())) {
296+ return hr;
297+ }
298+
299+ if (!m_hItem) {
300+ // 不正なアイテムを参照している
301+ return DISP_E_EXCEPTION;
302+ }
303+
304+ CComObject<CTreeItem>* pItem = NULL;
305+ if (FAILED(hr = CComObject<CTreeItem>::CreateInstance(&pItem))) {
306+ return hr;
307+ }
308+
309+ HTREEITEM hNewItem = TreeView_GetPrevSibling(m_hWnd, m_hItem);
310+ pItem->SetParam(m_hWnd, hNewItem);
311+
312+ return pItem->QueryInterface(IID_IUnknown, (void**)pVal);
313+}
314+
315+STDMETHODIMP CTreeItem::get_NextItem(/*[out, retval]*/ IUnknown* *pVal)
316+{
317+ // 次のアイテム
318+ *pVal = NULL;
319+
320+ HRESULT hr;
321+ if (FAILED(hr = InitialCheck())) {
322+ return hr;
323+ }
324+
325+ if (!m_hItem) {
326+ // 不正なアイテムを参照している
327+ return DISP_E_EXCEPTION;
328+ }
329+
330+ CComObject<CTreeItem>* pItem = NULL;
331+ if (FAILED(hr = CComObject<CTreeItem>::CreateInstance(&pItem))) {
332+ return hr;
333+ }
334+
335+ HTREEITEM hNewItem = TreeView_GetNextSibling(m_hWnd, m_hItem);
336+ pItem->SetParam(m_hWnd, hNewItem);
337+
338+ return pItem->QueryInterface(IID_IUnknown, (void**)pVal);
339+}
340+
341+STDMETHODIMP CTreeItem::get_ChildItem(/*[out, retval]*/ IUnknown* *pVal)
342+{
343+ // 子アイテム
344+ *pVal = NULL;
345+
346+ HRESULT hr;
347+ if (FAILED(hr = InitialCheck())) {
348+ return hr;
349+ }
350+
351+ if (!m_hItem) {
352+ // 不正なアイテムを参照している
353+ return DISP_E_EXCEPTION;
354+ }
355+
356+ CComObject<CTreeItem>* pItem = NULL;
357+ if (FAILED(hr = CComObject<CTreeItem>::CreateInstance(&pItem))) {
358+ return hr;
359+ }
360+
361+ HTREEITEM hNewItem = TreeView_GetChild(m_hWnd, m_hItem);
362+ pItem->SetParam(m_hWnd, hNewItem);
363+
364+ return pItem->QueryInterface(IID_IUnknown, (void**)pVal);
365+}
366+
367+STDMETHODIMP CTreeItem::get_Parent(/*[out, retval]*/ IUnknown* *pVal)
368+{
369+ // 親アイテム
370+ *pVal = NULL;
371+
372+ HRESULT hr;
373+ if (FAILED(hr = InitialCheck())) {
374+ return hr;
375+ }
376+
377+ if (!m_hItem) {
378+ // 不正なアイテムを参照している
379+ return DISP_E_EXCEPTION;
380+ }
381+
382+ CComObject<CTreeItem>* pItem = NULL;
383+ if (FAILED(hr = CComObject<CTreeItem>::CreateInstance(&pItem))) {
384+ return hr;
385+ }
386+
387+ HTREEITEM hNewItem = TreeView_GetParent(m_hWnd, m_hItem);
388+ pItem->SetParam(m_hWnd, hNewItem);
389+
390+ return pItem->QueryInterface(IID_IUnknown, (void**)pVal);
391+}
392+
393+//
394+void CTreeItem::SetParam(HWND hWnd, HTREEITEM hItem)
395+{
396+ m_hWnd = hWnd;
397+ m_hItem = hItem;
398+}
399+
--- a/TreeItem.h
+++ b/TreeItem.h
@@ -15,11 +15,11 @@ class ATL_NO_VTABLE CTreeItem :
1515 {
1616 public:
1717 CTreeItem()
18+ : m_hWnd(NULL)
19+ , m_hItem(NULL)
1820 {
19- m_hWnd = NULL;
20- m_hItem = NULL;
2121 }
22- static BOOL DeleteTreeItemWithData(HWND hWnd, HTREEITEM hItem);
22+
2323 //DECLARE_REGISTRY_RESOURCEID(IDR_TREEITEM)
2424
2525 DECLARE_PROTECT_FINAL_CONSTRUCT()
@@ -33,247 +33,25 @@ public:
3333 // ITreeItem
3434 public:
3535 STDMETHOD(IsValid)(/*[out,retval]*/BOOL* pResult);
36- static void CreateTreeItem(HWND hWnd, HTREEITEM hParent, LPCTSTR text, IUnknown** punkVal);
37- STDMETHOD(Sort)()
38- {
39- HRESULT ret = InitialCheck();
40- if (ret == S_OK) {
41- if (m_hItem) {
42- TreeView_SortChildren(m_hWnd, m_hItem, 0);
43- }
44- else {
45- // 不正なアイテムを参照している
46- ret = DISP_E_EXCEPTION;
47- }
48- }
49- return ret;
50- }
51- STDMETHOD(Expand)()
52- {
53- HRESULT ret = InitialCheck();
54- if (ret == S_OK) {
55- if (m_hItem) {
56- TreeView_Expand(m_hWnd, m_hItem, TVE_EXPAND);
57- }
58- else {
59- // 不正なアイテムを参照している
60- ret = DISP_E_EXCEPTION;
61- }
62- }
63- return ret;
64- }
65- STDMETHOD(Select)()
66- {
67- HRESULT ret = InitialCheck();
68- if (ret == S_OK) {
69- if (m_hItem) {
70- TreeView_SelectItem(m_hWnd, m_hItem);
71- }
72- else {
73- // 不正なアイテムを参照している
74- ret = DISP_E_EXCEPTION;
75- }
76- }
77- return ret;
78- }
79- STDMETHOD(Erase)()
80- {
81- HRESULT ret = InitialCheck();
82- if (ret == S_OK) {
83- if (m_hItem) {
84- if (DeleteTreeItemWithData(m_hWnd, m_hItem)) {
85- // 削除に成功したら、このハンドルを無効にする
86- m_hWnd = NULL;
87- m_hItem = NULL;
88- }
89- }
90- else {
91- // 不正なアイテムを参照している
92- ret = DISP_E_EXCEPTION;
93- }
94- }
95- return ret;
96- }
97- STDMETHOD(Create)(/*[in]*/VARIANT text,/*[out,retval]*/IUnknown** punkVal)
98- {
99- // アイテムの作成
100- *punkVal = NULL;
101- HRESULT ret = InitialCheck();
102- if (FAILED(ret)) {
103- return ret;
104- }
105-
106- if (m_hItem) {
107- CComVariant str;
108- ATL::CString mes(_TEXT(""));
109- if (str.ChangeType(VT_BSTR, &text) == S_OK) {
110- mes = str.bstrVal;
111- }
112- CreateTreeItem(m_hWnd, m_hItem, mes, punkVal);
113- return S_OK;
114- }
115- // 不正なアイテムを参照している
116- return DISP_E_EXCEPTION;
117- }
36+ STDMETHOD(Sort)();
37+ STDMETHOD(Expand)();
38+ STDMETHOD(Select)();
39+ STDMETHOD(Erase)();
40+ STDMETHOD(Create)(/*[in]*/VARIANT text,/*[out,retval]*/IUnknown** punkVal);
41+ STDMETHOD(get_Object)(/*[in,optional]*/VARIANT idx, /*[out, retval]*/ VARIANT *pVal);
42+ STDMETHOD(get_Text)(/*[out, retval]*/ BSTR *pVal);
43+ STDMETHOD(put_Text)(/*[in]*/ BSTR newVal);
44+ STDMETHOD(get_PrevItem)(/*[out, retval]*/ IUnknown* *pVal);
45+ STDMETHOD(get_NextItem)(/*[out, retval]*/ IUnknown* *pVal);
46+ STDMETHOD(get_ChildItem)(/*[out, retval]*/ IUnknown* *pVal);
47+ STDMETHOD(get_Parent)(/*[out, retval]*/ IUnknown* *pVal);
11848
119- STDMETHOD(get_Object)(/*[in,optional]*/VARIANT idx, /*[out, retval]*/ VARIANT *pVal)
120- {
121- // アイテムに関連付けられた連想配列オブジェクトを取得する
122- ::VariantInit(pVal);
123- HRESULT ret = InitialCheck();
124- if (!m_hItem) {
125- ret = DISP_E_EXCEPTION;
126- }
127- if (ret == S_OK) {
128- TVITEM itm = {0};
129- itm.mask = TVIF_PARAM;
130- itm.hItem = m_hItem;
131- if (TreeView_GetItem(m_hWnd, &itm)) {
132- IUnknown* pUnk = (IUnknown*)itm.lParam;
133- if (pUnk) {
134- pUnk->AddRef();
135- pVal->vt = VT_UNKNOWN;
136- pVal->punkVal = pUnk;
137- }
138- }
139- }
140- return ret;
141- }
142- HRESULT InitialCheck()
143- {
144- // ウィンドウが有効か検査する
145- if (m_hWnd && ::IsWindow(m_hWnd)) {
146- return S_OK;
147- }
148- return Error(IDS_ERR_TREEERROR);
149- }
150-
151- STDMETHOD(get_Text)(/*[out, retval]*/ BSTR *pVal)
152- {
153- // テキストの取得
154- HRESULT ret = InitialCheck();
155- if (!m_hItem) {
156- // 不正なアイテムを参照している
157- ret = DISP_E_EXCEPTION;
158- }
159-
160- if (ret == S_OK) {
161- TCHAR text[MAX_PATH] = {0};
162- TVITEM itm = {0};
163- itm.mask = TVIF_TEXT;
164- itm.hItem = m_hItem;
165- itm.pszText = text;
166- itm.cchTextMax = MAX_PATH;
167- if (TreeView_GetItem(m_hWnd, &itm)) {
168- CComBSTR ret(text);
169- *pVal = ret.Detach();
170- }
171- }
172- return ret;
173- }
174-
175- STDMETHOD(put_Text)(/*[in]*/ BSTR newVal)
176- {
177- // テキストの書き換え
178- HRESULT ret = InitialCheck();
179- if (!m_hItem) {
180- // 不正なアイテムを参照している
181- ret = DISP_E_EXCEPTION;
182- }
183- if (ret == S_OK) {
184- ATL::CString tmp(newVal);
185- TVITEM itm = {0};
186- itm.mask = TVIF_TEXT;
187- itm.hItem = m_hItem;
188- itm.pszText = tmp.GetBuffer();
189- itm.cchTextMax = tmp.GetLength(); // Setの場合は無視される
190- TreeView_SetItem(m_hWnd, &itm);
191- }
192- return ret;
193- }
194-
195- STDMETHOD(get_PrevItem)(/*[out, retval]*/ IUnknown* *pVal)
196- {
197- // 前のアイテム
198- *pVal = NULL;
199- HRESULT ret = InitialCheck();
200- if (!m_hItem) {
201- // 不正なアイテムを参照している
202- ret = DISP_E_EXCEPTION;
203- }
204- if (ret == S_OK) {
205- HTREEITEM hNewItem = TreeView_GetPrevSibling(m_hWnd, m_hItem);
206- CComObject<CTreeItem>* pItem = NULL;
207- if (pItem->CreateInstance(&pItem) == S_OK) {
208- pItem->SetParam(m_hWnd, hNewItem);
209- ret = pItem->QueryInterface(IID_IUnknown, (void**)pVal);
210- }
211- }
212- return ret;
213- }
214- STDMETHOD(get_NextItem)(/*[out, retval]*/ IUnknown* *pVal)
215- {
216- // 次のアイテム
217- *pVal = NULL;
218- HRESULT ret = InitialCheck();
219- if (!m_hItem) {
220- // 不正なアイテムを参照している
221- ret = DISP_E_EXCEPTION;
222- }
223- if (ret == S_OK) {
224- HTREEITEM hNewItem = TreeView_GetNextSibling(m_hWnd, m_hItem);
225- CComObject<CTreeItem>* pItem = NULL;
226- if (pItem->CreateInstance(&pItem) == S_OK) {
227- pItem->SetParam(m_hWnd, hNewItem);
228- ret = pItem->QueryInterface(IID_IUnknown, (void**)pVal);
229- }
230- }
231- return ret;
232- }
233- STDMETHOD(get_ChildItem)(/*[out, retval]*/ IUnknown* *pVal)
234- {
235- // 子アイテム
236- *pVal = NULL;
237- HRESULT ret = InitialCheck();
238- if (!m_hItem) {
239- // 不正なアイテムを参照している
240- ret = DISP_E_EXCEPTION;
241- }
242- if (ret == S_OK) {
243- HTREEITEM hNewItem = TreeView_GetChild(m_hWnd, m_hItem);
244- CComObject<CTreeItem>* pItem = NULL;
245- if (pItem->CreateInstance(&pItem) == S_OK) {
246- pItem->SetParam(m_hWnd, hNewItem);
247- ret = pItem->QueryInterface(IID_IUnknown, (void**)pVal);
248- }
249- }
250- return S_OK;
251- }
252- STDMETHOD(get_Parent)(/*[out, retval]*/ IUnknown* *pVal)
253- {
254- // 親アイテム
255- *pVal = NULL;
256- HRESULT ret = InitialCheck();
257- if (!m_hItem) {
258- // 不正なアイテムを参照している
259- ret = DISP_E_EXCEPTION;
260- }
261- if (ret == S_OK) {
262- HTREEITEM hNewItem = TreeView_GetParent(m_hWnd, m_hItem);
263- CComObject<CTreeItem>* pItem = NULL;
264- if (pItem->CreateInstance(&pItem) == S_OK) {
265- pItem->SetParam(m_hWnd, hNewItem);
266- ret = pItem->QueryInterface(IID_IUnknown, (void**)pVal);
267- }
268- }
269- return S_OK;
270- }
27149 //
272- void SetParam(HWND hWnd, HTREEITEM hItem)
273- {
274- m_hWnd = hWnd;
275- m_hItem = hItem;
276- }
50+ static BOOL DeleteTreeItemWithData(HWND hWnd, HTREEITEM hItem);
51+ static HRESULT CreateTreeItem(HWND hWnd, HTREEITEM hParent, LPCTSTR text, IUnknown** punkVal);
52+ HRESULT InitialCheck();
53+ void SetParam(HWND hWnd, HTREEITEM hItem);
54+
27755 protected:
27856 HWND m_hWnd;
27957 HTREEITEM m_hItem;
Show on old repository browser