更新された質問に関連性の高い新しい回答を投稿しています(賞金の対象となるために)。最初のプログレスバーが含まれている定期的な実行のために、この最小限のソースを考えてみましょう:
#include <Windows.h>
#include <CommCtrl.h>
#pragma comment(lib, "Comctl32.lib")
#include "resource.h"
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#define PROGRESSBAR_TIMER_ID 1
/*
* This callback is invoked each time the main window receives a message.
*/
INT_PTR CALLBACK DialogFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg) {
case WM_INITDIALOG: {
/*
* Fire a timer event each second.
*/
SetTimer(hwndDlg, PROGRESSBAR_TIMER_ID, 1000, NULL);
break;
}
case WM_TIMER: {
/*
* Catch the timer event that is fired each second. Increment the progress
* bar by 10% each time.
*/
HWND hwndProgressBar = GetDlgItem(hwndDlg, IDC_PROGRESS1);
UINT iPos = SendMessage(hwndProgressBar, PBM_GETPOS, 0, 0);
/*
* If the position is already full then kill the timer. Else increment the
* progress bar.
*/
if(iPos >= 100) {
KillTimer(hwndDlg, PROGRESSBAR_TIMER_ID);
} else {
SendMessage(hwndProgressBar, PBM_SETPOS, iPos + 10, 0);
}
break;
}
case WM_CLOSE:
EndDialog(hwndDlg, 0);
break;
default:
return FALSE;
}
return TRUE;
}
BOOL LaunchGUI(HINSTANCE hInstance)
{
return DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DialogFunc) == 0;
}
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
/*
* Initialise the common controls DLL.
*/
INITCOMMONCONTROLSEX iccex;
iccex.dwSize = sizeof(iccex);
iccex.dwICC = ICC_PROGRESS_CLASS | ICC_STANDARD_CLASSES | ICC_WIN95_CLASSES;
if(!InitCommonControlsEx(&iccex)) {
MessageBox(NULL, L"Problem initialising common controls DLL.", NULL, MB_OK);
return -1;
}
/*
* Launches the main GUI window.
*/
LaunchGUI(hInstance);
return ERROR_SUCCESS;
}
あなたが好きならば、あなたが正しい概念の理解を得るためのコードはほとんどですが、私はこのプログラムに関連する.rc
リソースファイルを投稿することができます。だから、すぐに要約し、このプログラム:
- は、単一のプログレスバー
- を含む単一のダイアログは、タイマーが起動するたびに
-
各秒を発射するためにタイマーを設定します含まれ、タイマーメッセージがにプログレスバーをトリガー
グラフィカルに更新され、それは次のようになります。
![Progress Bar](https://i.stack.imgur.com/ULfB5.png)
あなたの質問は、代わりにこのバーをDLLからインクリメントする方法です。あなたがする必要があるのは、DLLが進行状況バーを含むウィンドウと通信するための何らかの方法を許可することです。私はあなたがDLLをロードする方法はかなりわからないんだけど、これは私はそれがDLLインジェクションを介して行われていると仮定かかるだろうなアプローチです:
- ロード/
- は、DLLのエクスポートを持ってターゲットにDLLを注入それはインジェクタ/クライアントプロセスに関する情報を受け取ることを可能にするいくつかの初期化ルーチンである。
- クライアントの
GetProcAddress
とCreateRemoteThread
を使用して、この初期化ルーチンを呼び出します。
- DLLで、受信した情報を使用してクライアントの
HWND
を取得します。
具体的には、intialisationルーチンは次のようになります。
HWND hwndClient = NULL;
BOOL CALLBACK EnumProc(HWND hwnd, LPARAM lParam)
{
DWORD dwPID;
GetWindowThreadProcessId(hwnd, &dwPID);
if(dwPID == lParam) {
hwndClient = hwnd;
}
}
/*
* This code assumes the client has only one window. Given a PID, it populates
* a global to hold the window handle associated with the PID.
*/
DWORD WINAPI ReceiveClientPID(LPVOID dwPID)
{
EnumWindows(EnumProc, (LPARAM)dwPID);
}
クライアントコードは次のようなものかもしれません:
/*
* Depending on your method of injection, you should have a handle to the
* target process as well as a HMODULE of the injected DLL.
*/
void InitDLL(HANDLE hProcess, HMODULE hModule)
{
FARPROC lpInit = GetProcAddress(hModule, "ReceiveClientPID");
HANDLE hThread = CreateRemoteThread(hProcess, NULL, NULL,
(LPTHREAD_START_ROUTINE)lpInit, (LPVOID)GetCurrentProcessId(), NULL, NULL);
if(hThread == NULL) {
MessageBox(NULL, L"Problem calling init routine in DLL", NULL, MB_OK);
} else {
CloseHandle(hThread);
}
}
だから今、あなたがクライアントのHWND
を持っていますDLLを使用して、通信を行う方法を教えてください。その後、プログレスバーを変更し、クライアントにカスタムメッセージを指定することができます。
/*
* The new progress position can be passed in wParam.
*/
#define WM_UPDATE_PROGRESS_BAR (WM_APP + 1)
もDialogFunc
に対応するケースを追加することが対話する方法を実証するだけであったので(私たちは今WM_TIMER
コードを削除することができますプログレスバー):今
case WM_UPDATE_PROGRESS_BAR:
SendMessage(GetDlgItem(hwndDlg, IDC_PROGRESS1), PBM_SETPOS, wParam, 0);
break;
とクライアントのプログレスバーの変化をトリガするには、DLLは、単純に関係しています:
SendMessage(hwndClient, WM_UPDATE_PROGRESS_BAR, ..., 0);
WM_UPDATE_PROGRESS_BAR
もDLLで再定義する必要があることに注意してください。
/*
* Assumed progress is between 0 and 100. Otherwise it has to be
* normalised so this is the case (or the range of the progress bar
* in the client has to be changed).
*/
int my_progressor_callback(long progress)
{
SendMessage(hwndClient, WM_UPDATE_PROGRESS_BAR, progress, 0);
return 0;
}
あなたはちょうどあなたが実行ファイルと同じようにDLLでダイアログを表示することができますすべてのあなたの現在のコードでこれを合うように
。本当の概念上の違いはありません。しかし、あなたはおそらくそれをしたくないとマイクは言う。 –
大きな問題は、あなたのスレッドがUIスレッドになり(今ではプログレスバーを持つようになりますが)、メッセージをポンピングしないことです(calc_creationがCPUを嫌うためです)。スレッド間で作業を分割する必要があります。 –