You are not logged in.

  • Login

1

Saturday, January 7th 2012, 3:31pm

GUI und/in Dll

Hallo Community,

nachdem mein Problem mit der GUI gelößt wurde, habe ich nun eine einwandfrei funktionierende, hübsche Oberfläche (siehe unten) :)
Nun, diese Oberfläche würde ich gerne in eine Dll bringen, bzw. mit einer Dll kommunzieren lassen.
Werte, welche ich auf Knopdruck in der GUI einlese, möchte ich in dieser Dll verarbeiten:

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <windows.h>
#include <detours.h>

BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD Reason, LPVOID Reserved)
{
	switch(Reason)
	{
		case DLL_PROCESS_ATTACH:
			MessageBox(0,L"Attached.",L"Info",0);

			// SchreibeWert();
			// Funktion, welche einen eingelesenen Wert aus der GUI 
			// verwendet.

			break;
		case DLL_PROCESS_DETACH:
			MessageBox(0,L"Detached.",L"Info",0);
			break;
	}
	return TRUE;
}


Den grünen Bereich würde ich durch eine Funktion oder Quelltext ersetzen, welcher den eingelesenen Wert aus der GUI verwendet.
Genauso sollte es auch andersrum funktionieren, werte die in der Dll benutzt werden, sollen in der GUI angezigt werden. :)

Die Dll habe ich zu Testzwecken in den Prozess "Inkball" mit dem Programm "Winject" injeziert. Werte konnte ich aber hier nur durch die Benutzung von Hotkeys verändern.
Dies möchte ich nun erleichtern indem ich eine Kontrolloberfläche, eine GUI, zur Bedienung hinzuziehe :)

Meine einfache Oberfläche als Beispiel könnte so aussehen:

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <windows.h>
#include <stdio.h>
#include <cstdio>

#ifdef _UNICODE
#if defined _M_IX86
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_X64
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#else
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif
#endif

HWND hwndButton;
HWND hwndEdit;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hI, HINSTANCE hPrI, PSTR szCmdLine, int iCmdShow)
{
	LPWSTR szName = L"Fensterklasse";
	WNDCLASS wc;

	wc.style			= CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc		= WndProc;
	wc.cbClsExtra		= 0;
	wc.cbWndExtra		= 0;
	wc.hInstance		= hI;
	wc.hIcon			= LoadIcon (NULL,IDI_WINLOGO);
	wc.hCursor			= LoadCursor (NULL, IDC_ARROW);
	wc.hbrBackground	= (HBRUSH) GetStockObject(LTGRAY_BRUSH);
	//wc.hbrBackground	= CreateSolidBrush(RGB(0,0,0));
	wc.lpszMenuName		= NULL;
	wc.lpszClassName	= szName;
	RegisterClass(&wc);

	HWND hwnd = CreateWindow(szName, L"<Graphical User Interface>", WS_SYSMENU | WS_SIZEBOX,
						 	0,0,300,200,NULL,NULL,hI,NULL);

	ShowWindow(hwnd, iCmdShow);
	UpdateWindow(hwnd);

	MSG msg;
	while(GetMessage(&msg,NULL,0,0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	return msg.wParam;
}


LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;

	switch(message)
	{
	case WM_PAINT:
		hdc = BeginPaint(hwnd, &ps);
			SetBkMode(hdc,TRANSPARENT);
			SetTextColor(hdc,RGB(0,0,0));

			TextOut(hdc, 20, 20, L"Wert", 4);
		EndPaint(hwnd, &ps);
		return 0;
	case WM_CREATE:
		hwndButton = CreateWindow(L"button", L"Einlesen!", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
								160, 20, 100, 18, hwnd, (HMENU)1, GetModuleHandle(0),0);

		hwndEdit = CreateWindow(L"edit",L"50", WS_VISIBLE | WS_CHILD, 
								60,20,80,17,hwnd,0, GetModuleHandle(0),0);
		break;
	case WM_COMMAND:
		switch(wParam)
		{
		case 1:
		{
			wchar_t text[256];

			SendMessage(hwndEdit, WM_GETTEXT, 256, (LPARAM)text);
			MessageBox(hwnd, text, L"Edit -- Feld", MB_OK);

			break;
		}
		}
		break;

	case WM_DESTROY:
		PostQuitMessage(0);

		return 0;
		
	}
	
	return DefWindowProc(hwnd, message, wParam, lParam);
}


In dem rot gekennzeichneten Bereich lese ich einen Wert aus einem Edit Feld aus und speichere diesen in der Variable "text".
Diesen würde ich nun in der Dll verwenden wollen.

Allerdings bin ich ratlos, wie ich dies anstelle.
Google hat zwar einige seiten ausgespuckt, jedoch war dies nicht allzu verständlich für mich! :(

Über hilfreiche Antworten würde ich mich sehr freuen! :)
Mit freundlichen Grüßen
Infemo

2

Saturday, January 7th 2012, 4:07pm

Die Funktion DllMain wird beim laden und entladen der Bibliothek aufgerufen.

Da du MSVS verwendest, erstell doch dein Bibliothek über den intigrierten Wizzard:
Datei->Neu->Projekt ---> Visual C++ -> Win32 Projekt ---> DLL -> Fertig
Dann kriegst du schon in etwa das was du gepostet als Vorlage.

Nun kannst du hingeghen und eigen Funktionen definieren:

C/C++ Quellcode

1
int Add(int WertA, int WertB) { return WertA + WertB; }

Um diese in deinem Hauptprogramm verwenden zu können muss diese als "Exportiert" markiert werden:

C/C++ Quellcode

1
__declspec(dllexport) int Add(int WertA, int WertB) { return WertA + WertB; }

Wenn du nun die Bibliothek compilerst (Release) kriegst du zwei Dateien BibName.dll und BibName.lib.

Diese zweite Datei BibName.lib musst du in deinem Hauptprojekt linken, unter MSVS am einfachsten mit:

C/C++ Quellcode

1
#pragma comment(lib, "Pfad/BibName.lib")

Nun brauchst du nur noch den Prototyp der Funktion zu definieren und zu "importieren":

C/C++ Quellcode

1
__declspec(dllimport) int Add(int WertA, int WertB);

Und schliesslich kannst du die Funktion benutzen:

C/C++ Quellcode

1
int Sum = Add(4,5);

Anbei: Fortgeschritten arbeiten da, zur besseren Codeübersicht, jedoch in der Praxis mit Macros

PS: Sorg Bitte dafür das dein anderer (gleicher) Thread doch entfernt/gelöscht wird.

Mfg Rushh0ur

This post has been edited 1 times, last edit by "Rushh0ur" (Jan 7th 2012, 4:12pm)


3

Tuesday, January 10th 2012, 4:56pm

Hallo Rushh0ur,

vielen Dank für deine so umfang- und hilfreiche Antwort=)
Entschuldige meine späte Antwort, jedoch war ich in den letzten Tage ziemlich eingesapnnt :/

Also erstelle ich ein Projekt namen "Probe", so wie Sie es gesagt haben, bekomme ich zwei Header Dateien, zum einen eine stdafx.h und eine targetver.h.
Die Quelldateien sind dllmain.cpp, Probe.cpp und stdafx.cpp.

Compiliere ich dies ohne irgenetwas zu verändern bekomme ich eine Probe.dll, eine Probe.ilk und eine Probe.pdb.
Mit letzteren weis ich nichts anzufangen.

Allerdings fehlt hier weiterhin jede Spur einer GUI...muss ich dieses als neue Quelldatei hinzufügen?
Da ich neu im Forum bin, weis ich leider nicht wie ich dies löschen kann, allerdings habe ich das Thema als "Erledigt" markiert =)

Ich würde mich sehr über weitere Hilfestellungen freuen und bedanke mich nochmal bei Ihnen! :)

Mit freundlichen Grüßen
Infemo

4

Tuesday, January 10th 2012, 8:00pm

Die lib wird nur erstellt wenn auch Funktionen exportiert werden.

Ich hab dich etwas Falsch verstanden, das obige beschriebt wie du Funktionen einer DLL in deiner eigenen EXE verwenden kannst.

Da du jedoch die DLL in einer anderen EXE, vom Code her dir unbekannt, ladest/injectes steht dir nur die DllMain funktion zur verfügung.
Um nun dein Formular anzuzeigen musst du deinen Code in einem neuen Thread ausführen:

C/C++ Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include "stdafx.h"
#include "mylib.h"
 
// Thread Handle (Identifikation)
HANDLE	hThread = NULL;
 
// Eigene Threadroutin (Eigenes WinMain als Protyp in mylib.h definiert)
DWORD APIENTRY MyThreadRoutine(LPVOID lpThreadParameter)
{
	WinMain((HINSTANCE)lpThreadParameter, NULL, NULL, SW_SHOW);
	return 0;
}
 
// Dll Einstiegspunkt
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		// Thread erstellen
		DWORD idThread;
		hThread = CreateThread(NULL, NULL, &MyThreadRoutine, (LPVOID)hModule, 0, &idThread);
	break;
	case DLL_PROCESS_DETACH:
		// Eigenen Thread Terminieren, unschoen jedoch gits es keine andere Möglichkeit
		TerminateThread(hThread, -1); 
		CloseHandle(hThread);
	break;
	}
	return TRUE;
}


Mfg Rushh0ur

5

Wednesday, January 11th 2012, 4:14pm

Quoted

Die lib wird nur erstellt wenn auch Funktionen exportiert werden.
Achso, okay.

Quoted

Ich hab dich etwas Falsch verstanden, das obige beschriebt wie du Funktionen einer DLL in deiner eigenen EXE verwenden kannst.
Also zum teil möchte ich beides machen ;) 'Allerdings weniger Funktionen in meiner Exe Datei, sondern einfach nur Variablen in meiner Exe. Würde dies denn genaus so funktionieren, oder geht dies anders ?

Quoted

Da du jedoch die DLL in einer anderen EXE, vom Code her dir unbekannt, ladest/injectes steht dir nur die DllMain funktion zur verfügung.
Um nun dein Formular anzuzeigen musst du deinen Code in einem neuen Thread ausführen

Das heißt, dass ich in diesem Beispiel in die mylib.h die gesamte GUI packen müsste, damit ich ein Fenster habe, mit dem ich eingelesene Werte aus der GUI an die Dll übetragen kann?

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <windows.h>
#include <stdio.h>
#include <cstdio>

#ifdef _UNICODE
#if defined _M_IX86
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_X64
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#else
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif
#endif

HWND hwndButton;
HWND hwndEdit;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hI, HINSTANCE hPrI, PSTR szCmdLine, int iCmdShow)
{
	LPWSTR szName = L"Fensterklasse";
	WNDCLASS wc;

	wc.style			= CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc		= WndProc;
	wc.cbClsExtra		= 0;
	wc.cbWndExtra		= 0;
	wc.hInstance		= hI;
	wc.hIcon			= LoadIcon (NULL,IDI_WINLOGO);
	wc.hCursor			= LoadCursor (NULL, IDC_ARROW);
	wc.hbrBackground	= (HBRUSH) GetStockObject(LTGRAY_BRUSH);
	//wc.hbrBackground	= CreateSolidBrush(RGB(0,0,0));
	wc.lpszMenuName		= NULL;
	wc.lpszClassName	= szName;
	RegisterClass(&wc);

	HWND hwnd = CreateWindow(szName, L"<Graphical User Interface>", WS_SYSMENU | WS_SIZEBOX,
						 	0,0,300,200,NULL,NULL,hI,NULL);

	ShowWindow(hwnd, iCmdShow);
	UpdateWindow(hwnd);

	MSG msg;
	while(GetMessage(&msg,NULL,0,0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	return msg.wParam;
}


LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;

	switch(message)
	{
	case WM_PAINT:
		hdc = BeginPaint(hwnd, &ps);
			SetBkMode(hdc,TRANSPARENT);
			SetTextColor(hdc,RGB(0,0,0));

			TextOut(hdc, 20, 20, L"Wert", 4);
		EndPaint(hwnd, &ps);
		return 0;
	case WM_CREATE:
		hwndButton = CreateWindow(L"button", L"Einlesen!", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
								160, 20, 100, 18, hwnd, (HMENU)1, GetModuleHandle(0),0);

		hwndEdit = CreateWindow(L"edit",L"50", WS_VISIBLE | WS_CHILD, 
								60,20,80,17,hwnd,0, GetModuleHandle(0),0);
		break;
	case WM_COMMAND:
		switch(wParam)
		{
		case 1:
		{
			wchar_t text[256];

			SendMessage(hwndEdit, WM_GETTEXT, 256, (LPARAM)text);
			MessageBox(hwnd, text, L"Edit -- Feld", MB_OK);

			break;
		}
		}
		break;

	case WM_DESTROY:
		PostQuitMessage(0);

		return 0;
		
	}
	
	return DefWindowProc(hwnd, message, wParam, lParam);
}


Vielen Dank! Ich hoffe auf weitere Hilfeleistung :)

Liebe Grüße
Infemo

6

Wednesday, January 11th 2012, 6:15pm

Quoted


Das heißt, dass ich in diesem Beispiel in die mylib.h die gesamte GUI packen müsste, damit ich ein Fenster habe, mit dem ich eingelesene Werte aus der GUI an die Dll übetragen kann?

Kurz gesagt ja (jedoch eher in die cpp-Datei), insofern sich das Formular nicht in der Zielanwendung anderweitig schon vorhanden ist, dann kann therotisch natürlich auch das Formular der Zielanwendung verwendet werden.

Mfg Rushh0ur

7

Wednesday, January 11th 2012, 6:34pm

Also nicht in die mylib.h sondern in die dllmain.cpp innerhalb des Threads?

Social bookmarks