Jaka funkcja w winapi służy do pobierania tekstu z kontrolki klasy Edit ? GetWindowText nie pobiera tekstu, GetDlgItemText (działa tak samo) też nie, choć są w stanie pobrać np. nazwę okna. Nagłówkowałem się trochę i nic z tego nie wyszło. Ktoś gdzieś pisał, że próbował przez SendMessage, ale nazwa funkcji nie sugeruje, że służy ona do pobierania tekstu - argumenty też na to nie wskazują. Może SendMessageCallback ? Ale jeśli ktoś ma jakieś pojęcie na ten temat, to proszę o pomoc.
Dobrze wyczytałeś że należy użyć SendMessage.
Zajrzyj tutaj - masz gotowy przykład.
http://stackoverflow.com/questions/5469183/winapi-how-to-get-edits-text-to-a-stdstring
Ok, a jak tą metodę zadeklarować ? Próbowałem na kilka sposobów - jeden z najprostszych wyglądał tak:
int SendMessageA(HWND hWnd, String msg, int num1, int num2);
Ale do stringa nie było zwracane nic. Jak powinna wyglądać deklaracja i sposób użycia ?
No kolego - a dziwisz się że do Stringa nic nie jest zwracane?
Zamiast String użyj tablicy bajtowej o stałym rozmiarze : np. 256. Jak zostanie wypełniony to sobie go do stringa zrobisz. Pamiętaj o kodowaniu: wszytko w winapi jest w cp1250 także jak chcesz mieć ogonki to przed ładowaniem biblioteki poprzez JNA musisz takie coś ustawić:
System.setProperty("jna.encoding", "cp1250");
I pamiętaj ze jak zostanie wypełnione 11 bajtów a bufor dałeś na 256, to ta reszta będzie nullami.
Mniej więcej powinno wyglądać to tak:
byte[] odczytaneBajtyPola = new byte[256];
int zasieg = 0;
for (int i = 0; i < odczytaneBajtyPola.length; i++) {
if (odczytaneBajtyPola[i] != 0) {
zasieg = i + 1;
} else {
break;
}
}
byte[] odczytaneBajtyPoFormatowaniu = new byte[zasieg];
System.arraycopy(odczytaneBajtyPola, 0, odczytaneBajtyPoFormatowaniu, 0, zasieg);
String fieldDataString = null;
try {
fieldDataString = new String(odczytaneBajtyPoFormatowaniu , "CP1250");
} catch (Exception e) {
}
Jaki miałeś wynik - ten int ile Ci "oddał" po wywołaniu funkcji?
No kolego - a dziwisz się że do Stringa nic nie jest zwracane?
A to nie kwestia tego jak jest JNA zaimplementowane ? :) Poza tym to był jeden z desperackich przypadków jak już większość prób zawiodła. Tablice typu byte też wypróbowałem, a zrobiłem to tak:
byte[] text = new byte[512];
int result = User32.INSTANCE.SendMessageA(hWnd, text, 0, 0);
Zadeklarowałem w interfejsie jako:
int SendMessageA(HWND hWnd, byte[] msg, int num1, int num2);
A byta do Stringa wystarczy skonwertować w taki sposób
Native.toString(text)
Dla przykładu - pobieranie nazwy klasy już działa w taki sposób.
byte[] lpClassName = new byte[512];
User32.INSTANCE.GetClassNameA(hWnd, lpClassName, lpClassName.length);
String className = Native.toString(lpClassName);
A sam SendMessageA zwraca niestety 0.
Swoją drogą - dzięki za dodatkowe informacje odnośnie kodowania - przyda się.
Wiesz co - dopiero teraz spojrzałem co Ty chcesz tak naprawdę zrobić. hehe Trochę z d**y strony się za to wziąłeś. Lookaj:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644950(v=vs.85).aspx
Tam jest deklaracja taka:
LRESULT WINAPI SendMessage(
__in HWND hWnd,
__in UINT Msg,
__in WPARAM wParam,
__in LPARAM lParam
);
Jak widzisz drugi parametr to UINT czyli int bez znaku. Co Ty chcesz stamtąd wyciągnać jak to jest parametr "in" i jest to liczba?
Tam jest miejsce na liczbę, która określa rodzaj komunikatu do przetrawienia przez aplikacje docelową.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms632627(v=vs.85).aspx
To ta liczba o którą wydaje mi się Ci chodzi. Tekst który wyciagasz będzie w lParam i to wyciagniesz z linka co Ci kolo wkleił 2 posty wcześniej.
Fakt. Zadziałało :). Zmyliła mnie metoda GetClassName, bo miała argument out. A SendMessage ma wszędzie in. Ale pobranie poprzez referencje do tablicy bytów w parametrze WPARAM lub LPARAM zadziałało. Co do argumentu Msg nie byłem pewny jaki ustawić. Już jest ok.
Ale kodowanie wg twoich wskazówek nie działa :). Pobieram stringa "żółć". Po ustawieniu kodowania "cp1250" jest tak jak bez ustawiania - czyli "zólc" - tylko "ó" się zachowało. Po ustawieniu "UTF-8" jest "z?lc" - czyli gorzej, ale widać, że łapie zmiane kodowania - ale wygląda to tak, jak by kodowanie było ustawiane za późno, skoro "z", "l" i "c" nie są brane pod uwagę.
hmm....pokaż ten kod odpowiedzialny że rejerencję z wParam i lParan.
Poniżej metody pobierania i wstawiania tekstu:
public static final int WM_GETTEXT = 0x000D;
public static final int WM_SETTEXT = 0x000C;
public static String receiveText(HWND hWnd){
byte[] bytes = new byte[512];
int res = User32.INSTANCE.SendMessageA(hWnd, WM_GETTEXT, bytes.length, bytes);
String receivedText = Native.toString(bytes);
System.out.println("Received: " + receivedText + "; result: " + res);
return receivedText;
}
public static void sendText(HWND hWnd, String sentText){
byte[] bytes = sentText.getBytes();
int res = User32.INSTANCE.SendMessageA(hWnd, WM_SETTEXT, bytes.length, bytes);
System.out.println("Sent: " + Native.toString(bytes) + "; result: " + res);
}
Metoda wstawiania tekstu dziwnie działa - do tekstu dodaje string " |" albo "class". Przykładowe wywołanie:
sendText(child, "zdanie bez polskich liter")
Dla tego przypadku wkleja się tekst "zdanie bez polskich literclass". Dla testu w metodzie sendText robię tak:
bytes[bytes.length - 1] = 0
Wtedy wyświetla "zdanie bez polskich lite" - może na siłę dałoby się to obejść tak, że zawsze dodawałbym znak więcej, a potem go odcinał, ale to bez sensu. Pobranie bytów poprzez sentText.getBytes() robi najwyraźniej coś dziwnego - może ostatni bajt trzeba lekko przyciąć ?
A kodowanie ustawiam w mainie przed wywołaniem czegokolwiek:
System.setProperty("jna.encoding", "cp1250")