環境:VC++6.0
プログラミングメモ

・libc浮動小数点演算の速度比較

・関数近似

・便利なクラス

グラフの描画(PGPLOT)

・マルチバッファリング+早い描画関数(MFC)

マルチバッファリングは実用的な図形描画の常套手段でした

オブジェクト単位でなく、ビットマップ単位で描画したいとき
また、OnPaint や OnDraw で図形描画を行うとき、CDC::SetPixelV() は
非常に遅いので、高速描画のために別の手法を考える必要がありました

SetPixelV や DrawLine などの関数を置き換え可能な便利なクラスを作りました
CDialog::OnPaint() 関数などの内部で使います
クラスのデストラクタで CDC に内部バッファ画像が転送されます 


・SJIS を UTF-8 で出力

wchar_t がUTF-16に対応、S-JISなどから直接はできないので、


char* buf; wchar_t buf2[512];
// SJIS -> UTF-16 変換
MultiByteToWideChar(CP_ACP, 0, buf, -1, buf2, 512);
// UTF-16 -> UTF-8 変換
WideCharToMultiByte(CP_UTF8, 0, buf2, -1, buf, 512, NULL, NULL);

また、UTF-8では、ファイル先頭にUTF-8であることを示す記号 EF,BB,BF たとえば
      buf[0] = 0xEF; buf[1] = 0xBB; buf[2] = 0xBF; buf[3] = '\0'; //UTF-8
  を出力しないと、正しく認識されない可能性。(UTF-8N となる)

・VC++ でデバッグ

デバッグメッセージ出力API
OutputDebugString(...)
ASSERT(...) は、NULLで停止
VERIFY(...)は結果がNULLで停止
『Visual C++ドキュメント → Visual C++ ユーザーズガイド → Visual C++ プログラマーズガイド →
デバッグ → デバッグ技術、およびデバッグにおける問題と解決法 → ツールとヒント → ブレークポイントの使い方 : 追加情報』

・マルチスレッド処理

(1) とりあえずワーカースレッドを立てるには、スレッド関数

struct sRunProcData{
   ...
};
static UINT RunProc(LPVOID pParam){
   sRunProcData* pData = (*sRunProcData)pParam;
}
     



を書いて、親スレッドから
AfxBeginThread(RunProc, (LPVOID)&data);
とすればよい。スレッドの終了は子スレッド関数のreturnによる。

スレッドの終了を待つには、



     CWinThread* pTh = AfxBeginThread(RunProc, (LPVOID)NULL, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
     pTh->m_bAutoDelete = FALSE;
     pTh->ResumeThread();

     while(WaitForSingleObject(pTh->m_hThread, 100) == WAIT_TIMEOUT){
      // フリーズしないようにする
      MSG msg;
      while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
       TranslateMessage(&msg);
       DispatchMessage(&msg);
      }
     }
     delete pTh;
     

もしくは、


  CWinThread* pThread[THREAD_SIZE];
  HANDLE      hlst[THREAD_SIZE];
  for(int i=0; i<THREAD_SIZE; i++){
   pThread[i] = AfxBeginThread(RunFFTAdapriveProc, (LPVOID)&data[i],
    THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
   pThread[i]->m_bAutoDelete = FALSE;
   pThread[i]->ResumeThread();
   hlst[i] = pThread[i]->m_hThread;
  }
  
  WaitForMultipleObjects(THREAD_SIZE, hlst, TRUE, INFINITE);

  for(i=0; i<THREAD_SIZE; i++){
   delete pThread[i];
  }
     

と言う感じ。

・マルチ素手度尾応用

処理中に待ちウィンドウを表示する


 
 
CRect rc;
 HWND hNotifyWnd = CreateDialog(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDD_PROCESSING), this->m_hWnd, (DLGPROC)YCommonProc);
 ::ShowWindow(hNotifyWnd, SW_SHOW);
 GetClientRect(&rc);
 ::MoveWindow(hNotifyWnd, (rc.right-rc.left)/2-100, (rc.bottom-rc.top)/2-25, 200, 50, TRUE);

 CWinThread* pTh = AfxBeginThread(RunConvertProc, (LPVOID)NULL, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
 pTh->m_bAutoDelete = FALSE;
 pTh->ResumeThread();

 while(WaitForSingleObject(pTh->m_hThread, 100) == WAIT_TIMEOUT){
  // フリーズしないようにする
  MSG msg;
  while(::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
   ::TranslateMessage(&msg);
   ::DispatchMessage(&msg);
  }
 }
 delete pTh;
 
 ::DestroyWindow(hNotifyWnd);

 

     

・コマンド実行して標準出力を得る


static int ExecuteWithoutWindow(char* commandline){
 STARTUPINFO si;
 PROCESS_INFORMATION pi;
 memset(&si, 0, sizeof(si));
 memset(&pi, 0, sizeof(pi));
 si.cb = sizeof(si);
 if(CreateProcess(NULL, commandline, NULL, NULL, FALSE,
  CREATE_NO_WINDOW, NULL, NULL, &si, &pi) == 0){
  // failed
  return -1;
 }

 WaitForSingleObject( pi.hProcess, INFINITE );
 CloseHandle(pi.hThread);
 CloseHandle(pi.hProcess);
 return 0;
}


// コマンド実行して短い返事を得る
int YGetResponseText(char* commandline, char* response){
 // Create Pipe
 SECURITY_ATTRIBUTES attr;
 attr.nLength = sizeof(SECURITY_ATTRIBUTES);
 attr.bInheritHandle = TRUE;
 attr.lpSecurityDescriptor = NULL;

 //
 HANDLE hRead, hWrite;
 HANDLE hRead2, hWrite2;

 CreatePipe(&hRead, &hWrite, &attr, 0);
 SetHandleInformation(hRead, HANDLE_FLAG_INHERIT, 0);

 CreatePipe(&hRead2, &hWrite2, &attr, 0);
 SetHandleInformation(hWrite2, HANDLE_FLAG_INHERIT, 0);

 PROCESS_INFORMATION piProcInfo;
 STARTUPINFO siStartInfo;

 memset(&piProcInfo, 0, sizeof(PROCESS_INFORMATION));

 memset(&siStartInfo, 0, sizeof(STARTUPINFO));
 siStartInfo.cb = sizeof(STARTUPINFO);
 siStartInfo.hStdError = hWrite;
 siStartInfo.hStdOutput = hWrite;
 siStartInfo.hStdInput = hRead2;
 siStartInfo.dwFlags |= STARTF_USESTDHANDLES;

 // Create child process.
 int ret;

 ret = CreateProcess(NULL, commandline, NULL, NULL, TRUE,
 CREATE_NO_WINDOW, NULL, NULL,
 &siStartInfo, &piProcInfo);
 if(ret == NULL) return -1;

 DWORD dwRead;
 CHAR chBuf[512];

 for (;;) {
  ret = ReadFile( hRead, chBuf, 511, &dwRead, NULL);
  chBuf[dwRead] = '\0';
  strcat(response, chBuf);
  if( (ret == NULL) || dwRead == 0 ) break;
  break;
 }
 CloseHandle(piProcInfo.hProcess);
 CloseHandle(piProcInfo.hThread);

 CloseHandle(hRead);
 CloseHandle(hWrite);
 CloseHandle(hRead2);
 CloseHandle(hWrite2);

 return 0;
}


・ダイアログボックスの出しかた

// (1) 強制フォーカスのやつ(Modal Dialogbox):
 CTestDialog dlg;
 int ret = dlg.DoModal();

// (2) 出しっぱなしのやつ(Modeless Dialogbox):
 m_pDlg = new CTestDialog Dialog(this);

CTestDialog のコンストラクタで、
 Create(CTestDialog::IDD);
 ShowWindow(SW_SHOW);

OnOK() をオーバライドして、
 DestroyWindow();

PostNcDestroy() をオーバライドして、
 delete this;


// (3) 常に手前に表示
 m_pDlg->SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);

参照:http://support.microsoft.com/kb/403848/ja

・「ファイルを開く」ダイアログボックス

 CFileDialog fd(TRUE, "mp3", NULL, 0, "MP3 File(*.mp3)|*.mp3||", this);
 CFileDialog fd(FALSE, "mp3", NULL, OFN_OVERWRITEPROMPT, "MP3 File(*.mp3)|*.mp3||", this);
// 第一引数が TRUE で「開く」ダイアログ
// 第三引数は OFN_OVERWRITEPROMPT など、OPENFILENAME 構造体を参照

 if(fd.DoModal() == IDCANCEL) return; // ダイアログの表示
 CString fname = fd.GetPathName(); // ファイルのフルパスを返す


・CArchiveを使う

// ファイルを開く
 CFile file;
 if(!file.Open(filename, CFile::modeRead) ) {
  DebugMsg("Error in open file: [%s]", filename);
  return ;
 }
 CArchive ar(&file, CArchive::load);
 object.Seriarize(ar);

// ファイルを保存
 CFile file;
 if(!file.Open(filename, CFile::modeWrite | CFile::modeCreate)) {
  DebugMsg("Error in open file: [%s]", filename);
  return ;
 }
 CArchive ar(&file, CArchive::store);
 object.Seriarize(ar);

// ファイルが存在するか?
 if(GetFileAttributes(filename) != -1) { // ファイルが存在すれば
}

・CDocument を得るまで

// CMainFrame を得る
CMainFrame* pMainFrame = ((CMainFrame*)AfxGetMainWnd());
CxxxDoc* pDocument = (CxxxDoc*)pMainFrame->GetDocument();

 

・ファイルの列挙


    // rekkyo dll path
    WIN32_FIND_DATAA find;
    HANDLE hFind = FindFirstFileA(MyPath, &find);
    if(hFind == INVALID_HANDLE_VALUE) return;
    // first file
    MessageBoxA(NULL, find.cFileName, "", MB_OK);
    while(FindNextFileA(hFind, &find)){
        MessageBoxA(NULL, find.cFileName, "", MB_OK); // フルパスでない
    }

    FindClose(hFind);

・コピーコンストラクタ、演算子オーバーロード

 


・フォルダ内の全てのファイルを開く

char openFileName[512];
char openFileNameLst[512]; // ファイル名(ワイルドカードが使える)

WIN32_FIND_DATA fd;
HANDLE hSearch;
hSearch = FindFirstFile(openFileNameLst, &fd);
if(hSearch == INVALID_HANDLE_VALUE) {
 return -1;
}
while(1){
 strcpy(openFileName, "(フォルダ名)\\");
 strcat(openFileName, fd.cFileName);
 
 // ファイルを開く
 CFile file;
 if(!file.Open(openFileName, CFile::modeRead)) {
  return -1;
 }
 CArchive ar(&file, CArchive::load);
 obj.Seriarize(ar);

  // 次のファイル
 if(FindNextFile(hSearch, &fd) == NULL) {
  if( GetLastError() == ERROR_NO_MORE_FILES ){
   break;
  }else{
   MessageBox("Error in FindNextFile().\n");
   return;
  }
 }
}
FindClose(hSearch);

・bool, BOOL, VARIANT_BOOL 型

以下、VC++ 6.0 の動作
bool 型:
C 標準の boolean 型 です。
実際は 1 byte 型として実装される場合が多いです。したがって、
bool test[16]; ならば、

sizeof(bool) = 1, sizeof(test) = 16
となります。また、true = 1, false = 0 です。
vector<bool> はまた異なります。

BOOL 型:
Windows API では、BOOL 型が boolean 型として使われます。
<windef.h> で
#typedef int BOOL
のように、int 型として定義されています。したがって、
sizeof(BOOL) = 4
となります。TRUE と FALSE の2値をとりますが、定義は
TRUE = 1, FALSE = 0 です。

VARIANT_BOOL 型:
COM オブジェクトでの boolean 型として使われます。
<wtypes.h> で
#typedef short VARIANT_BOOL
のように、short 型として定義されています。したがって、
sizeof(VARIANT_BOOL) = 2
となります。VARIANT_TRUE と VARIANT_FALSE の2値をとりますが、定義は
VARIANT_TRUE = 0xFFFF, FALSE = 0 です。