ID_FILE_NEW ( [新規作成] ) ↓ CWinApp:OnFileNew() ↓ CDocManager::OnFileNew() ↓ CDocument::OnNewDocument() ID_FILE_OPEN ( [開く...] ) ↓ CWinApp:OnFileOpen() ↓ CWinApp:OpenDocumentFile() ↓ CDocManager::OpenDocumentFile() ↓ CDocument::OnOpenDocument() ↓ CDocument::Serialize() ↓ CDocument::SetPathName() ID_FILE_SAVE ( [上書き保存] ) ↓ CDocument::OnFileSave() ↓ CDocument::OnSaveDocument() ↓ CDocument::Serialize() ID_FILE_SAVE_AS ( [名前をつけて保存...] ) ↓ CDocument::OnFileSaveAs() ↓ CDocument::OnSaveDocument() ↓ CDocument::Serialize() ID_FILE_SAVE_AS ( [ファイル] メニューの [閉じる] ) ↓ CDocument::OnFileClose() ↓ CDocument::SaveModified() ↓ CDocument::OnCloseDocument() ↓ CMDIChildWnd::DestroyWindow() ↓ CMDIChildWnd::OnDestroy() ID_APP_EXIT ( [アプリケーションの終了] ) ↓ CWinApp::OnAppExit() ↓ CMDIFrameWnd::OnClose() ↓ CWinApp::SaveAllModified() ↓ CDocManager::SaveAllModified() ↓ CDocument::SaveModified() ↓ CMDIFrameWnd::DestroyWindow() ↓ CMDIFrameWnd::OnDestroy() ↓ CMDIChildWnd::OnDestroy() ↓ CDocument::OnCloseDocument() ↓ CWinApp::ExitInstance() メインウィンドウシステムの [閉じる] ↓ CMDIFrameWnd::OnClose() ↓ CWinApp::SaveAllModified() ↓ CDocManager::SaveAllModified() ↓ CDocument::SaveModified() ↓ CMDIFrameWnd::DestroyWindow() ↓ CMDIFrameWnd::OnDestroy() ↓ CMDIChildWnd::OnDestroy() ↓ CDocument::OnCloseDocument() ↓ CWinApp::ExitInstance() MDI 子フレームシステムメニューの [閉じる] ↓ CMDIChildWnd::OnClose() ↓ CDocument::SaveModified() ↓ CDocument::OnCloseDocument() ↓ CMDIChildWnd::DestroyWindow() ↓ CMDIChildWnd::OnDestroy() (注1)CDocument::DoSave は CDocument::OnSaveDocument を呼び出す。 (注2)CDocument::DoFileSave も CDocument::OnSaveDocument を呼び出す
--------------------------------------------------------- MFC AppWizard - ステップ 1 --------------------------------------------------------- 作成するアプリケーションの種類」 (*) SDI ( ) MDI ( ) ダイアログベース [ ] ドキュメント/ビュー アーキテクチャのサポート ---------------------------------------------------------
上記のウィザードを実行した後、以下のような修正を行う。 (通常、CView はヒープ上に取り、PostNcDestroy() で delete this するものらしい。)
#code c++ class CChildView : public CListView {
CChildView(); DECLARE_DYNCREATE(CChildView) // 追加};
IMPLEMENT_DYNCREATE(CChildView, CListView) // 追加
class CMainFrame : public CFrameWnd {
CChildView* m_pWndView;
};
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) {
if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1;
/*
if (!m_wndView.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL)) { TRACE0("Failed to create view window\n"); return -1; }
m_pWndView = (CChildView*)RUNTIME_CLASS(CChildView)->CreateObject(); if (!m_pWndView->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL)) { TRACE0("Failed to create view window\n"); return -1; }
}
#end また、以下の方法でも可能らしい。
#code c++ void CChildView::PostNcDestroy() {
CWnd::PostNcDestroy();
}
#end
[Visual Studio 6.0 ドキュメント] +[Visual C++ ドキュメント] +[サンプル] +[SDK Sample] +[COM Samples] +[COM SDK Samples] 「Click to open or copy the files for the COM samples.」のリンクをクリック。 (表示されるまでに、ちょっと時間がかかります。)
COM Sample Directory Tree The COM directory contains several sample COM applications. Directory Description COMMON Common code used by all the OLE samples. INCLUDE Common include files used by all the OLE samples. WINHLPRS Library of Windows helper functions used by MFRACT and DFVIEW. BROWSE OLE Automation controller that controls the BROWSEH inproc server. BROWSEH OLE Automation server that browses a type library. BTTNCUR Genertates BTTNCUR.DLL and BTTNCUR.LIB. CMALLSPY Sample IMallocSpy implementation. COM OLE tutorial samples. DEFO2V Source code for the OLE2VIEW default object viewer DLL. DFVIEW Docfile viewer. DISPCALC OLE Automation sample program. DISPDEMO Sample OLE Automation controller. DSPCALC2 OLE Automation sample program. GIZMOBAR Generates GIZMOBAR.DLL and GIZMOBAR.LIB. HELLO OLE automation server that implements a dual interface. LINES OLE Automation implementing collections and subobjects. MFRACT Custom interface sample. OLEAPT OLE Apartment model threading sample. OLESTD Generates OLESTD.LIB. OUTLINE Series illustrating converting a Windows application to OLE. SIMPCNTR Simple OLE container sample. SIMPDND Simple drag and drop sample. SIMPSVR Simple OLE server sample. SPOLY OLE Automation sample polygon drawing program. SPOLY2 OLE Automation sample polygon drawing program. TIBROWSE OLE Automation sample type library browser. Additional directories are created by these samples: LIB Will contain library files generated during the build. BIN Will contain many of the target .EXE and .DLL files. More details on each of these samples can be found in the readme.txt files found in these directories. To build all of these samples, use the following command nmake -a
[Component Development] +[Structured Strage] +[Using Structured Storage]
#code c++
#include <afx.h> #include <comdef.h> #import "C:\Program Files\Common Files\System\Ado\msado15.dll" rename("EOF", "adoEOF") using namespace ADODB; // 名前空間
#include <afxdisp.h> // COleSafeArray #include <afxtempl.h> // CArray typedef CArray< _variant_t, _variant_t& > CVariantArray;
class CSafeVariantArray : public CVariantArray { public:
operator LPVARIANT() { VariantArrayToSafeArray(); return (LPVARIANT)m_sa; }
private:
void VariantArrayToSafeArray() { COleSafeArray sa; int nSize = GetSize(); sa.CreateOneDim( VT_VARIANT, nSize ); for ( int i = 0; i < nSize; i++ ) { long lArrayIndex = (long)i; _variant_t vValue = GetAt(i); sa.PutElement( &lArrayIndex, &vValue ); } m_sa = sa; return; } COleSafeArray m_sa;
};
/* Sub FieldsAppendTest
Dim rsTmp Set rsTmp = CreateObject("ADODB.Recordset") With rsTmp.Fields .Append "Field1", adVarChar, 80, adFldIsNullable .Append "Field2", adVarChar, 80, adFldIsNullable End With rsTmp.Open
Dim vFieldList vFieldList = Array( "Field1", "Field2" ) Dim vValues vValues = Array( "aaa", "bbb" ) rsTmp.AddNew vFieldList, vValues vValues = Array( "CCC", "DDD" ) rsTmp.AddNew vFieldList, vValues rsTmp.MoveFirst Dim fld Dim strLine Dim strName strLine = "" For Each fld In rsTmp.Fields strName = fld.Name strLine = strLine & strName & vbTab Next WScript.Echo strLine Dim strValue While Not rsTmp.BOF And Not rsTmp.EOF strLine = "" For Each fld In rsTmp.Fields strValue = fld.Value strLine = strLine & "[" & strValue & "]" & vbTab Next WScript.Echo strLine rsTmp.MoveNext Wend
End Sub
void FieldsAppendTest() {
try { CoInitialize(NULL); ADODB::_RecordsetPtr rs; // Recordsetオブジェクト
// ADOオブジェクトの生成 rs.CreateInstance( __uuidof(ADODB::Recordset) );
rs->Fields->Append( L"Field1", adVarChar, 80, adFldIsNullable ); rs->Fields->Append( L"Field2", adVarChar, 80, adFldIsNullable ); rs->Open( vtMissing, vtMissing, adOpenForwardOnly, adLockOptimistic, adCmdUnknown );
// テーブルのフィールドリスト用の配列を作成します CSafeVariantArray vaFieldList; vaFieldList.Add( _variant_t( L"Field1" ) ); vaFieldList.Add( _variant_t( L"Field2" ) );
CSafeVariantArray vaValues; vaValues.Add( _variant_t( L"aaa" ) ); vaValues.Add( _variant_t( L"bbb" ) ); // 1レコード目 rs->AddNew( (LPVARIANT)vaFieldList, (LPVARIANT)vaValues );
vaValues.RemoveAll(); vaValues.Add( _variant_t( L"CCC" ) ); vaValues.Add( _variant_t( L"DDD" ) ); // 2レコード目 rs->AddNew( (LPVARIANT)vaFieldList, (LPVARIANT)vaValues );
rs->MoveFirst();
long i = 0; long nFields = rs->GetFields()->GetCount(); // 項目名 for ( i = 0; i < nFields; i++ ) { _bstr_t vName; _variant_t vValue; vName = rs->GetFields()->GetItem(i)->GetName(); _tprintf( _T("%s\t"), (LPCTSTR)vName ); } _tprintf( _T("\n") ); _tprintf( _T("-------------------------------------------------\n") );
// レコード表示 while ( !rs->GetBOF() && !rs->GetadoEOF() ) { for ( i = 0; i < nFields; i++ ) { _variant_t vValue; vValue = rs->GetFields()->GetItem(i)->GetValue(); _tprintf( _T("[%s]\t"), (LPCTSTR)(_bstr_t)vValue ); } _tprintf( _T("\n") ); rs->MoveNext(); }
rs->Close(); } catch ( _com_error& e ) { _tprintf( _T("e.Description = [%s]\n"), (LPCTSTR)e.Description() ); return; } catch ( ... ) { _tprintf( _T("Fatal Error!\n") ); return; }
CoUninitialize();
}
int main( int argc, char* argv[] ) {
FieldsAppendTest();
return 0;
}
#end
文字列の配列として COleSafeArray を使うのが味噌らしい。
[プラットフォーム SDK ドキュメント] +[プラットフォーム SDK ドキュメント] +[データ アクセス サービス] +[Microsoft ActiveX Data Objects (ADO)] +[セクション V: 付録] +[付録 C: ADO を使用したプログラミング] +[Microsoft Visual C++ での ADO の使用] +[Visual C++ での ADO プログラミング]
SafeArray は、別のデータ型の配列を格納する構造化データ型です。 SafeArray が "Safe (安全)" であるとされているのは、各配列の 次元の範囲に関する情報を SafeArray が格納し、配列要素に対す るアクセスをそれらの範囲内に制限するためです。 「ADO API リファレンス」で、「メソッドやプロパティが配列を取 得する」、または「返す」というとき、メソッドやプロパティが、 ネイティブ C/C++ 配列ではなく SafeArray を取得すること、また は返すことを意味します。 たとえば、Connection オブジェクト OpenSchema メソッドの 2 番 目のパラメータには、バリアント型 (Variant) の値の配列が必要 です。これらのバリアント型 (Variant) の値は、SafeArray の要 素として渡され、その SafeArray は別の Variant の値として設定 されます。OpenSchema の 2 番目の引数として渡されるのは、別の バリアント型 (Variant) です。 さらに別の例として、Find メソッドの最初の引数がバリアント型 (Variant) で、その値が一次元の SafeArray の場合、AddNew の 最初と 2 番目の任意の引数は、それぞれ一次元 SafeArray であり、 GetRows メソッドの戻り値は、値が二次元 SafeArray のバリアン ト型 (Variant) です。
Visual Basic では、バリアント型 (Variant) 配列は Dim ステー トメントを使ってコーディングします。または、次のコード例にも あるように Array 関数を使うこともできます。 Public Sub ArrayOfVariants Dim cn As ADODB.Connection Dim rs As ADODB.Recordset Dim fld As ADODB.Field cn.Open "DSN=pubs", "sa", "" rs = cn.OpenSchema(adSchemaColumns, Array(Empty, Empty, "authors", Empty)) For Each fld in rs.Fields Debug.Print "Name = "; fld.Name Next fld rs.Close cn.Close End Sub 次の Visual C++ の例では、_variant_t に使う SafeArray の使用方法を示します。 注意 次の注意事項は、コード例のコメント部分に対応しています。 1. もう一度、TESTHR() インライン関数を定義して、既存のエラー処理機能を利用します。 2. 必要なのは一次元配列のみであり、汎用の SAFEARRAYBOUND 宣 言と SafeArrayCreate 関数の代わりに SafeArrayCreateVector が使えます。次の例は、 SafeArrayCreate を使ったときのコードを示します。 SAFEARRAYBOUND sabound[1]; sabound[0].lLbound = 0; sabound[0].cElements = 4; pSa = SafeArrayCreate(VT_VARIANT, 1, sabound); 3. 列挙定数 adSchemaColumns で識別したスキーマは、4 つの定数 列 (TABLE_CATALOG、TABLE_SCHEMA、TABLE_NAME、および COLUMN_NAME) に関連付けられています。 したがって、4 つの要素を持つバリアント型 (Variant) の値の 配列が作成されます。 次に、3 番目の列 TABLE_NAME に対応する制約値を指定します。 返される Recordset は、さまざまな列で構成されています。こ のサブセットが制約列です。各戻り行に対する制約列の値は、 対応する制約値と同じにします。 4. SafeArrays に慣れていると、終了前に SafeArrayDestroy() が 呼び出されないことに驚かれるかもしれません。実際、このと きに SafeArrayDestroy() を呼び出すと実行時例外処理になり ます。これは、_variant_t が範囲外になると SafeArray が解 除されて、vtCriteria のデストラクタが VariantClear() を呼 び出すためです。手動で _variant_t を消去せずに SafeArrayDestroy を呼び出すと、デストラクタは無効な SafeArray ポインタを消去しようとします。 SafeArrayDestroy を呼び出すと、次のようなコードになります。 TESTHR(SafeArrayDestroy(pSa)); vtCriteria.vt = VT_EMPTY; vtCriteria.parray = NULL; ただし、_variant_t で SafeArray を管理する方がずっと簡単です。
#code c++
#import "c:\Program Files\Common Files\System\ADO\msado15.dll" \ no_namespace rename("EOF", "EndOfFile") #include <stdio.h>
// Note 1 inline void TESTHR( HRESULT _hr ) { if FAILED(_hr) { _com_issue_error(_hr); } } void main(void) { CoInitialize(NULL); try { _RecordsetPtr pRs("ADODB.Recordset"); _ConnectionPtr pCn("ADODB.Connection"); _variant_t vtTableName("authors"), vtCriteria; long ix[1]; SAFEARRAY *pSa = NULL; pCn->Open("DSN=pubs;User ID=sa;pwd=;Provider=MSDASQL;", "", "", adConnectUnspecified); // Note 2, Note 3 pSa = SafeArrayCreateVector(VT_VARIANT, 1, 4); if (!pSa) { _com_issue_error(E_OUTOFMEMORY); } // Specify TABLE_NAME in the third array element (index of 2). ix[0] = 2; TESTHR(SafeArrayPutElement(pSa, ix, &vtTableName)); // There is no Variant constructor for a SafeArray, so manually set the // type (SafeArray of Variant) and value (pointer to a SafeArray). vtCriteria.vt = VT_ARRAY | VT_VARIANT; vtCriteria.parray = pSa; pRs = pCn->OpenSchema(adSchemaColumns, vtCriteria, vtMissing); long limit = pRs->GetFields()->Count; for (long x = 0; x < limit; x++) { printf("%d: %s\n", x+1, ((char*) pRs->GetFields()->Item[x]->Name)); } // Note 4 pRs->Close(); pCn->Close(); } catch (_com_error &e) { printf("Error:\n"); printf("Code = %08lx\n", e.Error()); printf("Code meaning = %s\n", (char*) e.ErrorMessage()); printf("Source = %s\n", (char*) e.Source()); printf("Description = %s\n", (char*) e.Description()); } CoUninitialize(); }
#end
[MSDN ライブラリ 2001 年 10 月] +[Visual Studio 6.0 ドキュメント] +[Visual C++ ドキュメント] +[リファレンス] +[Microsoft Foundation Class リファレンス] +[ATL (Active Template Library) リファレンス] +[解説] +[ATL サービス]
[ユーザー インターフェイス デザインおよび開発] +[ユーザー インターフェイス デザインおよび開発 +[アクセシビリティ] +[技術文書] +[キーボード ユーザー インターフェイス設計のガイドライン]
cl test.cpp /P
#code c++
int main( int argc, char* argv[] ) { printf( "_MAX_PATH = [%d]\n", _MAX_PATH ); return 0; }
#end
#code c++
int main( int argc, char* argv[] ) { printf( "_MAX_PATH = [%d]\n", 260 ); return 0; }
#end
#code c++
#include "resource.h"
#include "afxres.h"
STRINGTABLE DISCARDABLE BEGIN
IDS_TEST "Resource File Test [%s]"
END
#end
#code c++
#define IDS_TEST 1000
#end
#code c++
#include <afx.h>
#include "resource.h"
int main( int argc, char* argv[] ) {
CString strData; strData.Format( IDS_TEST, _T("aaa") ); _tprintf( _T("strData = [%s]\n"), (LPCTSTR)strData ); return 0;
}
#end
rc test.rc cl test.cpp test.res /MT
>test strData = [Resource File Test [aaa]]
5.8.1 通常のユーザーとして実行した場合にアプリケーションがエラーを発生する理由 5.8.2 アプリケーションが失敗する理由を判定する方法 セキュリティが原因となってアプリケーションが失敗する理由を判定する方法 ・Windows イベントビューア →[ローカルポリシー] - [監査ポリシー] - [特権使用の監査] ・RegMon( http://www.sysinternals.com/ で入手可能 ) ・FileMon( http://www.sysinternals.com/ で入手可能 ) →Access Denied のエラーチェック
[Platform SDK ドキュメント] +-[Security] +-[Cryptography] +-[CryptoAPI] +-[About CryptoAPI] +-[Using CryptoAPI] +-[CryptoAPI Reference]
[Security (英語)] +-[Security (General)] +-[SDK Documentation] +-[Cryptography] +-[About Cryptography] +-[Using Cryptography] +-[Cryptography Reference]
<暗号化処理の初期化> 1. デフォルトキーコンテナの取得。 CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, 0) 2. デフォルトキーコンテナの作成(1. の処理に失敗した場合) CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET) <暗号化処理> 1. デフォルトキーコンテナの取得。 CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, 0) 2. ハッシュオブジェクトの作成。 CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash) 3. パスワード文字列のハッシュの取得。 CryptHashData(hHash, (BYTE*)szPassword, dwLength, 0) 4. パスワードのハッシュを元にセッションキーを作成。 CryptDeriveKey( hProv, CALG_RC4, hHash, CRYPT_EXPORTABLE, &hKey) 5. 暗号化処理。 CryptEncrypt(hKey, 0, TRUE, 0, pbBuffer, &dwLength, dwLength ) 6. セッションキーの削除 CryptDestroyKey(hKey) 7. ハッシュオブジェクトの削除。 CryptDestroyHash(hHash); 7. ハッシュオブジェクトの削除。 CryptDestroyHash(hHash) 8. キーコンテナの解放 CryptReleaseContext(hProv, 0) <復号化処理> 1. デフォルトキーコンテナの取得。 CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, 0) 2. ハッシュオブジェクトの作成。 CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash) 3. パスワード文字列のハッシュの取得。 CryptHashData(hHash, (BYTE*)szPassword, dwLength, 0) 4. パスワードのハッシュを元にセッションキーを作成。 CryptDeriveKey( hProv, CALG_RC4, hHash, CRYPT_EXPORTABLE, &hKey) 5. 暗号化処理。 CryptDecrypt(hKey, 0, TRUE, 0, pbBuffer, &dwLength, dwLength ) 6. セッションキーの削除 CryptDestroyKey(hKey) 7. ハッシュオブジェクトの削除。 CryptDestroyHash(hHash) 8. キーコンテナの解放 CryptReleaseContext(hProv, 0)
#access