JNA - pobieranie tekstu z kontrolki klasy Edit

0

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.

0

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

0

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 ?

0

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?

0

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ę.

0

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.

0

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ę.

0

hmm....pokaż ten kod odpowiedzialny że rejerencję z wParam i lParan.

0

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")

1 użytkowników online, w tym zalogowanych: 0, gości: 1