Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[WinAPI] Odbieranie powiadomień EN_UPDATE i EN_CHANGE

Ostatnio zmodyfikowano 2013-04-21 13:26
Autor Wiadomość
berkov
Temat założony przez niniejszego użytkownika
[WinAPI] Odbieranie powiadomień EN_UPDATE i EN_CHANGE
» 2013-04-21 01:00:33
hey ho

Mam Dialog a w nim rozne Controls. Dla potrzeb przykladu zalozmy ze mowa o:
#define IDC_przyklad     1001

IDC_przyklad to EDITTEXT.

Dialog na ktorym sie Control znajduje obslugiwany jest przez:
BOOL CALLBACK DlgProcModalless( HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam )

Chcialbym miec mozliwosc korekty wpisu uzytkownia w tym Control'u, ponownie dla przykladu, tak aby program automatycznie poprawil wpis uzytkownika z "x" na "z" oraz aby nie pozwolil wpisac literki "a".
w MSDN jest:
EN_UPDATE
    WPARAM wParam;
    LPARAM lParam;

 Parameters
   wParam - The LOWORD contains the identifier of the edit control. The HIWORD specifies the notification code.
   lParam - A handle to the edit control.

Tylko jak to sie ma do mojego DlgProcModalless?

Poczatek kodu (nie wiem wogole czy dobrze):
C/C++
BOOL CALLBACK DlgProcModalless( HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam )
{
    switch( Msg ) {
    case EN_UPDATE:
        {
            switch( LOWORD( lParam ) )
            {
            case 1001: //lub IDC_przyklad:
                // tu ma byc kod "validujacy" ale jak wsadzilem MessageBox zeby zobaczyc czy wogole ta czesc jest wywolywana to niestety okazalo sie ze pomimo wpisu do Control - IDC_przyklad zaden popup sie nie pojawia.

Rozumiem uzycie notification codes ale tylko do poziomu lParam albo wParam, ale jak sie dostac dalej (LOWORD, HIWORD)...?
Czyli na tym konkretnym przykladzie jak dostac HWND do danego Control'u i jak dowiedziec sie o tym ze uzytkownik np wpisal "x" z klawiatury?

dzieki
berkov
P-80949
DejaVu
» 2013-04-21 01:11:28
a co zrobisz w przypadku, gdy ktoś zrobi ctrl+v? Nie ma sensu czaić się na konkretne wciśnięcie klawisza, bo ctrl+v takie 'zabezpieczenie' po prostu ominie.
P-80951
berkov
Temat założony przez niniejszego użytkownika
» 2013-04-21 01:25:10
Juz teraz nie pamietam ktora z dwoch notyfications CHANGE czy UPDATE, ale pamietam ze gdzies wyczytalem ze kteoras z nich obejmuje zmiany rozumiane jako rowniez wklejanie ze schowka. poza tym logicznie myslac CTR+V to "zmiana", wiec tym bym sie narazie nie martwil. Przynajmniej pocwicze notyfication codes
P-80952
Monika90
» 2013-04-21 07:51:18
Sprawdzenie w dokumentacji zabiera aż minutę:
EN_UPDATE:
The parent window of the edit control receives this notification message through the WM_COMMAND message.
P-80953
xevuel
» 2013-04-21 07:53:51
The parent window of the edit control receives this notification code through a WM_COMMAND message.

wParam
    The LOWORD contains the identifier of the edit control. The HIWORD specifies the notification code.
lParam
    A handle to the edit control.
Czyli odbierasz WM_COMMAND, porównujesz identyfikator/uchwyt kontrolki (czy jest to ten, który ma być, a nie np. innego Edita) a następnie:
C/C++
switch( HIWORD( wParam ) )
{
case EN_UPDATE:
    //do something;
    break;
}
P-80954
berkov
Temat założony przez niniejszego użytkownika
» 2013-04-21 09:54:29
Hey ho!

@Monika90 - "dzieki serdecznie" za fatyge ale kompletnie nie pomoglas! Jak powiedzialem czytalem dokumentacje ale jej nie zrozumialem, dla poczatkujacych zrozumienie takich "referencji" moze byc dosc ciezkie, dlatego tez wlozylem post na tym forum. Nie pamieta wol jak cieleciem byl!

@xevuel, dzieki, teraz juz rozumiem ze EN_UPDATE to HIWORD( wParam ) pochodzacy z Msg WM_COMMAND. Myslalem ze EN_UPDATE to Msg i sam przynosi lParam i wParam.

Wpisalem wiec taki kod:
C/C++
BOOL CALLBACK DlgProcModalless( HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam )
{
    switch( Msg )
    {
    case WM_COMMAND:
        {
           
            switch( LOWORD( wParam ) )
            {
               
            case IDC_zapisz: jakiskodzapisujacy(); break;
            case IDC_anuluj: DestroyWindow( hwnd ); break;
            case IDC_przyklad: {
                    if( HIWORD( wParam ) == EN_UPDATE )
                    { MessageBox( 0, "zmodyfikowano text", 0, 0 ); } else { MessageBox( 0, "Wszystko pozostale", 0, 0 ); }
                } break;
            }
        }
        break;
       
        default: return FALSE;
    }
   
    return TRUE;
}

Ale cos dalej nie dziala, bo po odpaleniu tego kodu jak tylko klikne mysza na Control IDC_przyklad dostaje z jakies 30 razy TYLKO pop-up "Wszystko pozostale" a jak juz sie "uspokoi" i wpisuje cos z klawiatury to nie ma wogole zadnej reakcji. Co dziwniejsze - jesli klikne na inny kontrol i wroce kliknieciem spowrotem to rowniez juz nie dostane zadnego komunikatu.

Czyli dziala tylko 30x (i to zle) za pierwszym kliknieciem a pozniej nic i nigdy nie wyrzuca "zmodyfikowano text".

jakis pomysl?
berkov
P-80955
xevuel
» 2013-04-21 11:31:27
Kod wydaje się być prawidłowy.. Stwórz jak najkrótszy, ale kompletny przykład który zachowuje się jak mówisz.

//Edit: Weź pod uwagę, że wywołanie MessageBoxa spowoduje wysłanie EN_SETFOCUS i EN_KILLFOCUS. Do takiego "debugowania" lepiej użyć funkcji która nie wymaga interakcji z użytkownikiem (najbanalniejszy przykład - SetWindowText dla głównego okna).
P-80959
berkov
Temat założony przez niniejszego użytkownika
» 2013-04-21 12:25:01
ok, masz racje, MessageBox powodowal "samowywolanie" i zapetlenie
 wiec wprowadzilem male zmiany
C/C++
BOOL CALLBACK DlgProcModalless( HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam )
{
    switch( Msg )
    {
    case WM_COMMAND:
        {
           
            switch( LOWORD( wParam ) )
            {
               
            case IDC_zapisz: jakiskod(); break;
            case IDC_anuluj: DestroyWindow( hwnd ); break;
            case IDC_przyklad: {
                    if( HIWORD( wParam ) == EN_UPDATE )
                    { MessageBox( 0, "EN_UPDATE!", 0, 0 ); } else { MessageBeep( 0 ); }
                } break;
            }
        }
        break;
       
        default: return FALSE;
    }
   
    return TRUE;
}

Teraz dostaje system beep za kazdym dotknieciem, zmiana lub opuszczeniem IDC_example Control, przynajmniej teraz to tylko jedno beepniecie a nie jak wczesniej niekonczace sie wywolanie MessageBox wiec jakis postep jest. Ale nadal nie dostaje MessageBoxu ani raz, nie rozumiem. Czyzby naprawde EN_UPDATE niegdy nie byl przekazywany? Jesli tak to czy mozna sprawdzic jaki inny komunikat jest przekazywany?


W razie czego Dialog wywoluje tak:
C/C++
hDialogMen = CreateDialog( GetModuleHandle( 0 ), MAKEINTRESOURCE( 1000 ), hwMain, DlgProcModalless );
ShowWindow( hDialogMen, SW_SHOW );

resources.rc:
C/C++
LANGUAGE 0, SUBLANG_NEUTRAL
IDD_FVT DIALOGEX 0, 0, 319, 200
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "Verdana"
{
    PUSHBUTTON "Anuluj", IDC_zapisz, 35, 160, 60, 14, WS_TABSTOP
    DEFPUSHBUTTON "Zapisz", IDC_anuluj, 242, 160, 60, 14, WS_TABSTOP
    EDITTEXT IDC_przyklad, 214, 73, 55, 14, ES_AUTOHSCROLL | WS_TABSTOP
}

resources.h:
C/C++
#define IDC_OK 103
#define IDC_CANCEL 104
#define IDD_DYNAMIC 222
#ifndef IDC_STATIC
#define IDC_STATIC (-1)
#endif
#define IDC_przyklad                            1001
#define IDD_zapisz                              1002
#define IDD_anuluj                              1003

btw. probowalem rowinez z EN_CHANGE i efekt taki sam jak z EN_UPDATE.
P-80961
« 1 » 2
  Strona 1 z 2 Następna strona