Skocz do zawartości

[RichEdit]Wstawianie do nowej lini


Recommended Posts

Napisano

Pewnie że się da ;)

Najpierw musisz przesunąć kursor do nowej linii:

int line_index = SendMessage(hEdit, EM_LINEFROMCHAR, (WPARAM) -1, 0) ;

line_index++ ;

int pos = SendMessage(hEdit, EM_LINEINDEX, line_index, 0) ;
SendMessage(hEdit, EM_SETSEL, pos, pos) ;

Komunikat EM_LINEFROMCHAR (zapomnialem go opisać w arcie..echh) zwraca na podstawie pozycji znaku numer linii w kontrolce richedit...jeśli podamy -1 wtedy zwróci nam bieżącą linię...następnie zwiększamy o jeden (możesz sprawdzać czy jest to ostania linia [EM_GETLINECOUNT i wtedy przejść do poprzedniej(--) lub pierwszej(0)). Mamy już właściwą linie...teraz wysyłamy EM_LINEINDEX i otrzymujemy nową pozycję znaku...potem tylko ustwiamy wiadomością EM_SETSEL pozycję kursora...

No i wypadałoby wstawić tekst...

EM_REPLACESEL
fCanUndo = (BOOL) wParam ;
lpszReplace = (LPCTSTR) lParam ;

fCanUndo określasz czy operacja wstawiania może być cofnięta..no a lpszReplace tekst do (w naszym przypadku nie mamy zaznaczonego przedziału) wstawienia...

to tyle, jeśli masz jakieś pytania to wal śmiało...coś na pewno znajdziesz w ostatnim arcie..który postaram się uzupełnić o pominięte przeze mnie infromacje...hehe wybaczcie... :$

pozdrawiam

Napisano

Jeśli richedit i wogle edit ma ustawione enabled na true to jest wszystko w porządku...nie rozumiem...znaczy, że jest aktywny, jakby miał enabled false to wtedy byłby nieaktywny...czy kod wtedy zadziała...myśle, że powinien zadziałać...ale nie jestem pewnien na 100% - sprawdź...hehe...jeśli nie chcesz żeby można było kliknąc i nic zmieniać w richedicie to ustaw flage EM_READONLY...a właściwie to nie mieszam już bo do końca nie wiem do czego ci to potrzebne i jaki chcesz osiągnąć efekt..hehe...możesz potraktować to jako pytanie..ale nie musisz... ;)

pozdrawiam

  • 2 weeks later...
Napisano

Zmarax...zrób tego richedita daj mu ES_READONLY i to co napisałem w pierwszym poście...będzie działać...swoją drogą zastanawiam się czy to co działa na richedicie w tym wypadku nie zadziała na zwykły edit...hmm...próbuj zmarax, próbuj ;)

Napisano

Witam

Nie wiem czy dobrze zrozumiałem ale jeżeli chodzi o procedurę wstawiającą tekst jako dowolną nową linię w RichEdit (w Edit też prawdopodobnie działa) to zobacz coś takiego (kod w MASM :D ):

InsertText proc uses esi hEdit:HWND, LineIndex: DWORD, lpText: LPSTR
LOCAL SelStart, LineLen: DWORD 
;Rozmiar bufora rowny maksymalemu długości linji + 2
LOCAL Buf[1024]: BYTE  
LOCAL lpNewLine[3]: BYTE 

    lea esi, lpNewLine          
    mov dword ptr [esi], 0A0Dh  ;Znaki nowej linii do buforka #13#10
    .if LineIndex > 0
        invoke SendMessage, hEdit, EM_LINEINDEX, LineIndex, 0
        mov SelStart, eax
        .if eax >= 0
            ;Kopiujemy wstawiany Tekst do buforka 
            invoke lstrcpy, addr Buf, lpText
            ;Dołanczamy znaki nowej linii #13#10 do buforka
            invoke lstrcat, addr Buf, addr lpNewLine
        .else
            invoke SendMessage, hEdit, EM_LINEINDEX, LineIndex - 1, 0
            mov SelStart, eax
            .if eax < 0
                ret
            .endif
            invoke SendMessage, hEdit, EM_LINELENGTH, eax, 0
            mov LineLen, eax
            .if eax < 0
                ret
            .endif 
            add SelStart, eax ;SelStart = SelStart + LineLen
            ;Kopiujemy znaki nowej linii #13#10 do buforka
            invoke lstrcpy, addr Buf, addr lpNewLine
            ;Dołanczamy wstawiany Tekst do buforka 
            invoke lstrcat, addr Buf, lpText                  
        .endif  
        invoke SendMessage, hEdit, EM_SETSEL, SelStart, SelStart
        invoke SendMessage, hEdit, EM_REPLACESEL, 0, addr Buf             
    .endif  
        ret
                
InsertText endp

Parametry:
hEdit:HWND - Uchwyt RichEdit
LineIndex: DWORD - Nr. linii do ktorej ma być wstaiony tekst
lpText: LPSTR - Adres buforka z tekstem który ma być wstawiony

Jeżeli chcesz dodać nową linię na końcu tekstu to wcześniej wysyłasz komunikat EM_GETLINECOUNT który zwraca ilosć linii w RichEdit-a więc to podstawiasz jako LineIndex

A jeżeli chcesz aby RightEdit zachowywał sie jak Static (Nie można edytować, brak migającego kursora, nie można zaznaczać tekstu) to kiedyś wymyśliłem 9_9 takie rozwiązanie (choć nie wiem czy najlepsze). Ustawiasz mu styl ES_READONLY i pomocą SubClassingu podmieniasz procedurę obsługi RichEdit na coś takiego:

RichEditProc proc hRichEdit:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD

     .if (uMsg==WM_CHAR) || (uMsg == WM_LBUTTONDOWN) 
        ;Wywołaj starą procedurę obsługi okna
        invoke CallWindowProc,lpRichEdit,hRichEdit,uMsg,wParam,lParam
        invoke HideCaret, hRichEdit ;Ukryj kursor
        sub eax, eax ;Zwroc 0
        ret
     .elseif (uMsg == WM_SETFOCUS) || (uMsg == WM_SETCURSOR)  
        sub eax, eax ;Zwroc 0
        ret                     
     .endif
     ;Wywołaj starą procedurę obsługi okna
     invoke CallWindowProc,lpRichEdit,hRichEdit,uMsg,wParam,lParam
     ret

RichEditProc endp

Celowo nie robiłem nic przez EnableWindow ponieważ jak próbowałem ustawić na FALSE to nie mogłem zmienić koloru tła tekstu.

Jeżeli jednak nie o to chodziło :$ to sorry
Pozdro

Napisano

Dobra więc powiem wszystkim o co mi chodzi:
Chcę zrobić okno programu, a na dole umieszczony małe RichEdit na górze duży RichEdit (tak jak w Gadu-Gadu) i jak napisze coś na dole to żeby mi to wskakiwało na góre a na dole znikało :D

Napisano

Witam

No to nie rozumiem w czym problem przecież napisalem jak wstawić tekst do nowej linii a z resztą chyba niema problemu :/

;Pobierz tekst z RighEdit
invoke GetWindowText, hRichEditMaly, addr szBufText, 1024
;Sprawdź do której linii wstawić
invoke SendMessage, hRichEditDuzy, EM_GETLINECOUNT, 0, 0
;Kod funkcji InsertText masz w moim poprzednim poście
;w eax jest numer linii d o której wstawiamy tekst 
;(w tym wypadku na koniec) 
invoke InsertText, hRichEditDuzy, eax, addr szBufText
;Wyczyść tekst
invoke SetWindowText, hRichEditMaly, NULL

PS: Moja funkcja InsertText ma pewną wadę: Jeżeli w RichEdit znajduje sie już tekst wstawiony np. przez SetWindowText to na jego końcu nie ma znaków końca linii #13#10 więc przed wstawieniem tekstu trzeba wstaić te znaki na początku wstawianego tekstu. Jeżeli natomiast użyjesz InsertText na wyczyszczonym RichEdit to i czały czas za pomocą tej funkcji dokładasz nowy tekst to niema problemu :)
PS2: Jeżeli cos nie działa albo nie umiesz przetłymaczyć tego na C++ to napisz spróbuję wyjaśnić o co chodzi. Bo ten kod działa sprawdziłem (przynajmniej w tekscie bez obrazków) :D

Pozdro

Napisano

Witam ponownie

Rzeczywiście ten mój pierwszy sposób jest baaardzo zły...jednak żeby wyjść z tego wszystkiego z honorem ;) zmarax masz tutaj funckje:

bool WstawNowaLinia(char * tekst, HWND hEdit)
{
    char nowalinia[255] ;
    int line, line_count, line_len, start ;
    
    if((tekst[0] != (char) NULL) && (hEdit))
    {
        line_count = SendMessage(hEdit, EM_GETLINECOUNT, (WPARAM) 0, (LPARAM) 0) ;
        line       = SendMessage(hEdit, EM_LINEINDEX, (WPARAM) (line_count - 1), (LPARAM) 0) ;
        line_len   = SendMessage(hEdit, EM_LINELENGTH, (WPARAM) line, (LPARAM) 0) ;
        
        start = line + line_len ;
                
        SendMessage(hEdit, EM_SETSEL, start, start) ;                
                
        if(line)
        wsprintf(nowalinia, "\n%s", tekst) ;
        else
        wsprintf(nowalinia, tekst) ;
        
        SendMessage(hEdit, EM_REPLACESEL, (WPARAM) 1, (LPARAM) nowalinia) ;
        return true ;
    }    
    return false ;
}    

Wyjaśnienie:

Jeśli wszystko zostało prawidłowo przekazane to najpierw pobieramy sobie ilość lini, a potem (ideks jest liczony od zera ilość linie nie) za pomocą EM_LINEINDEX otrzymujemy odpowiednie współrzędne lini. Pobieramy długość tej linii i (w start) otrzymujemy pozycję ostatniego znaku w tekście..ostaniego znaku(!!!!!!!!!!)....kurde..a nie lepiej zrobić tak:

bool WstawNowaLinia(char * tekst, HWND hEdit)
{
    char nowalinia[255] ;
    int start ;
    
    if((tekst[0] != (char) NULL) && (hEdit))
    {
        start = (GetWindowTextLength(hEdit) -1) ;
                
        SendMessage(hEdit, EM_SETSEL, start, start) ;                
                
        if(start != -1)
        wsprintf(nowalinia, "\n%s", tekst) ;
        else
        wsprintf(nowalinia, tekst) ;
        
        SendMessage(hEdit, EM_REPLACESEL, (WPARAM) 1, (LPARAM) nowalinia) ;
        return true ;
    }    
    return false ;
}    

Pobieramy ilość tekstu i odejmuje jeden (w końcu ma być to index, liczony od 0). No a potem to już wszystko jasne...

Jeśli chcesz zrobić tak jak w gg...to nie ma problemu. Ustawiasz sobie flage ES_READONLY (w gg można zaznaczać). Potem jakiś przycisk, który będzie dodawał nowe linie. Oto przykładowa obsługa zdarzenia dla takiego przycisku:

char pomoc[255] ;
//----
case WM_COMMAND:
    if(wParam == 100) //załużmy, że id tego przycisku to 100
    {
        GetWindowText(hZdanie, pomoc, 255) ; //pobieramy sobie tekst do dodania
        WstawNowaLinie(pomoc, hDialog) ; //wstawiamy go do okna dialogu (tak jak w gg ;))
        SetWindowText(hZdanie, "") ; //czyścimy pole do wprowadzania tekstu
    }    
    break ;
//----
break ;

I nie wciskać kitu, że nie działa bo sprawdzałem...hehe
I to tyle. Pozdrawiam ;)

Napisano

Witam

Jak widzę już po problemie, codeguy rzeczywiście Twoja procedurka jest bardziej zoptymalizowana od mojej bo moja była pisana pod kątem wstawienia nowej linii w podanej linii tekstu a w tym wypadku (przy wstawianiu na końcu) rzeczywiście można prościej. Mi się też to przyda. Thanx

Pozdrawiam

Napisano

Witam
hDialog w przykładzie to uchwyt kontrolki do której dodajesz tekst (durzego RichEdit-a) zwraca go funkcja CreateWindow lub CreateWindowEx w zależności którą funkcją tworzysz wspomnianego RichEdit-a.
hZdanie to jest uchwyt kontrolki do której wpisujesz tekst
Pozdro

Napisano

Witam
Tworzysz sobie zmienne globalne i deklarujesz.

#include <windows.h>
// -= tu deklaracje pozostałych modółów =-
// -= tu ewentualne nagłówki procedur =-
// -= a tutaj deklaracje zmiennych globalnych np.: =>
HWND hDialog;
HWND hZdanie;
// -= no i dopiero dalej właśiwy kod programu =-

Mam nadzieję, że teraz już wszystko jest jasne :D
Podro

Napisano
#include <winsock2.h>
#include <windows.h>
static TCHAR nazwa[]=TEXT("okno");
char wyslij[1000];
int ID, kom;
SOCKET klient;
HWND hDialog, hZdanie;
bool WstawNowaLinia(char * tekst, HWND hEdit)
{
   
    int line, line_count, line_len, start ;
   
    if((tekst[0] != (char) NULL) && (hEdit))
    {
        line_count = SendMessage(hEdit, EM_GETLINECOUNT, (WPARAM) 0, (LPARAM) 0) ;
        line       = SendMessage(hEdit, EM_LINEINDEX, (WPARAM) (line_count - 1), (LPARAM) 0) ;
        line_len   = SendMessage(hEdit, EM_LINELENGTH, (WPARAM) line, (LPARAM) 0) ;
       
        start = line + line_len ;
               
        SendMessage(hEdit, EM_SETSEL, start, start) ;               
               
        if(line)
        wsprintf(wyslij     , "\n%s", tekst) ;
        else
        wsprintf(wyslij, tekst) ;
       
        SendMessage(hEdit, EM_REPLACESEL, (WPARAM) 1, (LPARAM) wyslij) ;
        return true ;
    }   
    return false ;
}       

LRESULT CALLBACK ProcOkna(HWND uchwyt,UINT komunikat,WPARAM wParam,LPARAM lParam)
{
  switch (komunikat)
  {
        case WM_CREATE:
        //
        break;
        case WM_COMMAND:
        ID = LOWORD(wParam);
                kom = HIWORD(wParam);
                if((kom == BN_CLICKED)&&(ID=2)) {
                         ;


                        GetDlgItemText(uchwyt, 3, wyslij, 999);
                        GetWindowText(hZdanie, wyslij, 999);
                        send(klient, wyslij, sizeof(wyslij), 0);
                        WstawNowaLinia(wyslij, hDialog);
                    SetDlgItemText(uchwyt, 3, "");
        }
                break;
                case WM_DESTROY:
        PostQuitMessage(0);
        break;

        case WM_KEYDOWN:
            switch (wParam)
            {
            case VK_ESCAPE:
            PostQuitMessage(0);
            break;
            }
        break;

default:
return (DefWindowProc(uchwyt,komunikat,wParam,lParam));
}
return(0L);
} 

Nie wiem dalej nie działa... ;(
Jeszcze raz dzięki tym którzy mi odpowiadają :D

Napisano

Może spróbuj tak


#include <windows.h>

char wyslij[1000];
int ID,kom;
HWND hDialog,hZdanie;

LRESULT CALLBACK ProcOkna(HWND uchwyt,UINT komunikat,WPARAM wParam,LPARAM lParam)
{
   switch(komunikat)
   {
        case WM_CREATE:
        //
        break;
        
        case WM_COMMAND:
           ID=LOWORD(wParam);
           kom=HIWORD(wParam);
           if((kom==BN_CLICKED)&&(ID=2))
      {
                   GetWindowText(hZdanie,wyslij,999);
                   int start=GetWindowTextLength(hDialog);
                   SendMessage(hDialog,EM_SETSEL,start,start);
         SendMessage(hDialog,EM_REPLACESEL,0,(long)wyslij);
                   SendMessage(hDialog,EM_REPLACESEL,0,(long)"\n");
                   SetWindowText(hZdanie,"");
           }
        break;

        // itd. .......
        // ............
    }
}

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Gość
Odpowiedz...

×   Wkleiłeś zawartość bez formatowania.   Usuń formatowanie

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Utwórz nowe...