環境: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
です。
|
|