Text aus anderem Fenster lesen
-
Hi!
Es ist schon eine Weile her, daß ich mich mit C++ unter Windows beschäftigt habe und ich hoffe, daß mir hier jemand helfen kann.
Ich möchte ein Textfeld aus einem anderen Programm auslesen und dann z.B. in einer Messagebox auswerfen. Hier mein Code, aber leider bekomme ich ihn nicht zum Laufen:
#include <iostream.h> #include <windows.h> #include <windows.h> #include <stdlib.h> #include <string.h> using namespace std; std::string GetWindowText(HWND windowHandle) { //define variable "text" std::string text; //get length of the text, 1 for termination unsigned int size = SendMessage(windowHandle, WM_GETTEXTLENGTH, 0, 0) + 1; //resize variable to length text.resize(size); //copy text to buffer -> this is better than GetWindowText() SendMessage(windowHandle, WM_GETTEXT, size, reinterpret_cast<LPARAM>(&text[0])); return text; } int main() { HWND window = NULL; while(window == NULL) //search window title) { window = FindWindow(NULL, "KMP Weather Backup 2.8a SEP98"); Sleep(100); } if(!window) cout << "Application not found!" << endl; else { content = GetWindowText(HWND 0x001D020A) MessageBox(NULL, "result", content, MB_OK); } return 0; }Herzlichen Dank für Hilfe.
Peter (eigentlich ohne LKW)
-
Willst Du den Fenstertitel auslesen, dann könntest Du auch "GetWindowText()" benutzen, oder willst Du ein Textfeld einer anderen Anwendung auslesen? Für zweiteres benötigtest Du auch die ID, bzw. HWND des Textfeldes, das Du auslesen willst.
-
Exhumed schrieb:
Willst Du den Fenstertitel auslesen, dann könntest Du auch "GetWindowText()" benutzen, oder willst Du ein Textfeld einer anderen Anwendung auslesen? Für zweiteres benötigtest Du auch die ID, bzw. HWND des Textfeldes, das Du auslesen willst.
Ich möchte das Textfeld auslesen. Ich kenne sowohl das Window Handle des Textfelds, als auch die Window- bzw. Control ID desselbigen.
Ich dachte, ich muss zunächst das Handle des anderen Programms ermitteln?!
-
lkwpeter schrieb:
Ich dachte, ich muss zunächst das Handle des anderen Programms ermitteln?!
Ja, und wenn Du dann hast müßte das Ganze mit einem:
SendDlgItemMessage(HWND_Anwendung,ID_Control,WM_GETTEXT,size,lpszBuf);
funktionieren.
Jetzt sehe ich das Du ein C++-String verwendest. Ich glaube nicht das Dein Cast funktioniert. Verwende doch einen "stinknormalen" C-Array.
zb.: LPTSTR lpszBuf. Diesen allokierst Du dann mit "HeapAlloc()", vorher hast Du ja die Textlänge ermittelt.
-
Exhumed schrieb:
Ja, und wenn Du dann hast müßte das Ganze mit einem:
SendDlgItemMessage(HWND_Anwendung,ID_Control,WM_GETTEXT,size,lpszBuf);
funktionieren.
Jetzt sehe ich das Du ein C++-String verwendest. Ich glaube nicht das Dein Cast funktioniert. Verwende doch einen "stinknormalen" C-Array.
zb.: LPTSTR lpszBuf. Diesen allokierst Du dann mit "HeapAlloc()", vorher hast Du ja die Textlänge ermittelt.*rotwert* Ich habe das letzte Mal vor 6 Jahren mit C++ gearbeitet und hängt jetzt wirklich in der Luft.
Hintergrund des Ganzen ist: Ich habe hier eine Klimasoftware, die die Daten in einem ganz komischen Format speichert und keine Export-Funktion hat. Der Programmierer ist vor 4 Jahren gestorben und jetzt möchte ich gerne die gesammelten Daten in eine neue DB migrieren. Pro "Seite" gibt es 10 Werte und es gibt rund 70.000 Seiten - also manuell nicht durchführbar

Eigentlich müsste ich gar nicht nach einem Fenster suchen, sondern könnte dem Script auch die Window- bzw. Control-Handles in einer Liste übergeben. Die kann man ja mit Spy++ usw. herausfinden.
Ich muss das Programm nur 1x durchlaufen lassen, danach brauche ich den Code voraussichtlich nicht wieder...
Okay, abgeschweift:
Kannst Du mir noch ein wenig dabei helfen? Ich verzweifle echt
-
So sollte das jetzt eigentlich klappen...
#include <iostream> #include <windows.h> #include <windows.h> #include <stdlib.h> #include <string.h> using namespace std; HWND handles[] = { 0x000115E8, 0x000115E8, 0x000115E8, 0x000115E8, 0x000115E8 }; const int num_handles = sizeof(handles) / sizeof(handles[0]); std::string GetWindowText(HWND windowHandle) { //define variable "text" std::string text; //get length of the text, 1 for termination unsigned int size = SendMessage(windowHandle, WM_GETTEXTLENGTH, 0, 0) + 1; //resize variable to length text.resize(size); //copy text to buffer -> this is better than GetWindowText() SendMessage(windowHandle, WM_GETTEXT, size, reinterpret_cast<LPARAM>(&text[0])); return text; } int main() { std::string content; int c; for (c = 0; c < num_handles; c++) { content = GetWindowText((HWND)); MessageBox(NULL, content.c_str(), "contents of the item", MB_OK); } return 0; }
-
...ich war x eine "unechte" Hawai-Pizza essen...
So weit ich weiß, sind die HWNDs variabel, d.h. sie werden bei jedem Programmstart verändert. Wenn Du die IDs verwendest, bist Du auf jeden Fall auf der sicheren Seite. Diese sind fest mit den Ressourcen verknüpft.
Dein "reinterpret_cast<LPARAM>(&text[0]))" ist wirklich schauderhaft.

-
[quote="Exhumed"]...ich war x eine "unechte" Hawai-Pizza essen...
So weit ich weiß, sind die HWNDs variabel, d.h. sie werden bei jedem Programmstart verändert. Wenn Du die IDs verwendest, bist Du auf jeden Fall auf der sicheren Seite. Diese sind fest mit den Ressourcen verknüpft.
Exhumed schrieb:
muss es eh nur 1x durchlaufen lassen. Also sind die Control-IDs immer die gleichen? Na super... wie bekomme ich das jetzt umgebaut?
[quote="Exhumed"]Dein "reinterpret_cast<LPARAM>(&text[0]))" ist wirklich schauderhaft.

Hab' ich aus einem anderen Forum geklaut. Also traditionell umbauen? Okay, wird gemacht. Bist du noch etwas wach?
-
lkwpeter schrieb:
Ich möchte das Textfeld auslesen. Ich kenne sowohl das Window Handle des Textfelds, als auch die Window- bzw. Control ID desselbigen.
Wenn Du die Control-ID hast, dann verwende "SendDlgItemMessage()", Die Parent-HWND bekommst Du ja mit: FindWindow(NULL, "KMP Weather Backup 2.8a SEP98");
danach abeitest Du alle IDs ab, so wie Du jetzt die HWNDs abarbeitest. WM_GETTEXTLENGTH u WM_GETTEXT bleibt gleich. Verwende einen Char-Buffer von 1000 Zeichen, statt einen C++-String. Dann brauchst Du auch nicht WM_GETTEXTLENGTH, vorrausgesetzt die Daten überschreiten nicht 1000 Zeichen. (Wenn es mehr sind einfach Buffer herhöhen) Da du das Programm nur für diesen speziellen Fall benötigst ist das unkomplizierter.
Also:std::string GetWindowText(HWND windowHandle,UINT idControl) { //define variable "text" std::string text; char szBuf[1000]; SendDlgItemMessage(windowHandle,idControl, WM_GETTEXT, 1000, szBuf); text = szBuf; return text; }Das müßte dann klappen.
Jetzt muß ich aber in's Bettchen
-
Danke, Exhumed für den Code - aber ich bekomme es noch nicht mal hin, meinen Code fehlerfrei in Visual C++ 2010, Express Edition zu compilieren und ehrlich gesagt kann ich mit den Fehlermeldungen nicht viel anfangen

-
So, jetzt klappt mein Code wenigstens endlich!
#include "StdAfx.h" #include <iostream> #include <windows.h> #include <stdlib.h> #include <string.h> #include <string> #include <cstring> using namespace std; HWND handles[] = { (HWND) 0x124880 }; const int num_handles = sizeof(handles) / sizeof(handles[0]); std::string GetWindowText(HWND windowHandle) { //define variable "text" std::string text; //get length of the text, 1 for termination unsigned int size = SendMessage(windowHandle, WM_GETTEXTLENGTH, 0, 0) + 1; //resize variable to length text.resize(size); //copy text to buffer -> this is better than GetWindowText() SendMessageA(windowHandle, WM_GETTEXT, size, reinterpret_cast<LPARAM>(&text[0])); return text; } int main() { std::string content; int c; for (c = 0; c < num_handles; c++) { content = GetWindowText(handles[c]); MessageBoxA(NULL, content.c_str(), "contents of the item", MB_OK); } return 0; }
-
Nur ein kleiner Hinweis: wenn du sagst, dass du
namespace stdverwendest, dann solltest dustd::vor den Entitäten wie string weglassen. Entweder das eine oder das andere.VG,
Rew.