|
第4日目に作ったファイルの全検索ルーチンをコンパイルした方には分かったと思うが、検索が終了するまでリストボックスには何も表示されない。これはループの中で処理をしているため、ループから出るまで画面の再描画が起こらないためである。 これは格好が悪い・・・・。ループの中でも再描画をかけるためにはループの中でCPUに他のルーチンにに処理を行わせるようにすればよい。以前使用していた Borland C++ ではこの処理を行うためにGetApplication()->PumpWaittingMessages()という関数を呼んでいた。この関数を呼ぶとループの中だろうがお構い無しにCPUは別の処理を行い、その処理が終わり次第帰ってきてループ内の処理を行うようになる。 Visual C++ でも同じように出来るのでは?と思いやってみる・・・・やっぱりできない。困った・・・・。仕方がないので別の方法を考えてみた。やるべき事は同じなので同じような名前で同じような機能の関数が用意されているはずである。 試しに「 Pump 」でヘルプを引いてみる・・・・あった!名前が似ているのが気に入った!(オイオイ)ヘルプの中には以下のようにしたら〜と書いてある。 |
|
|
while ( bDoingBackgroundProcessing )
{
while ( ::PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
{
if ( !PumpMessage( ) )
{
bDoingBackgroundProcessing = FALSE;
::PostQuitMessage( );
break;
}
}
// MFC でアイドリング処理を行う
LONG lIdle = 0;
while ( AfxGetApp()->OnIdle(lIdle++ ) )
;
// ここでバックグラウンドでの処理の一部を行う
// ために OnIdle への別の呼び出しを使う
}
|
|
|
なにやら大変そうである。知らない単語がいっぱいだ・・・・これはいかん、もっと使いやすくなければいかん。こんな事をするならば、自分自身で PumpMessages をオーバーライドする方が簡単そうである。知人に PumpMessageについていろいろと聞いてみた。すると、下記のようなコードで今やりたい事が実現できるらしいという事がわかった。
void PumpMessages()
{
MSG msg;
while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
::TranslateMessage(&msg);
::DispatchMessage (&msg);
}
}
上記のコードの関数を作り、ループの中から呼んでみると・・・・・できた!ループの中で処理をしながらリストボックスにファイル名が入っていく!これで良かったようだ。下記にそのコードを掲載する
void PumpMessages()
{
MSG msg;
while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
::TranslateMessage(&msg);
::DispatchMessage (&msg);
}
}
#include <io.h>
#include <direct.h>
void CDeleteManDlg::SearchDir(char* path)
{
_finddata_t ffblk;
long handle;
int pathcount = 0;
_chdir(path);
if( (handle = _findfirst("*", &ffblk)) != -1){
do{
if( (strcmp(ffblk.name, ".") != 0 &
& strcmp(ffblk.name, "..") != 0 ) ){
if( ffblk.attrib == _A_SUBDIR ){
strcat(path, ffblk.name);
strcat(path, "\\");
SearchDir(path);
}
else
m_LstFileName.AddString(ffblk.name);
}
//ここで処理を回す
PumpMessages();
}while( _findnext(handle, &ffblk) != -1 );
}
path[strlen(path) - 1] = '\0';
char* p = strrchr(path, '\\');
if(p == NULL)
return;
*(p + 1) = '\0';
}
このサンプルソースコードはここからダウンロードできる。
|