Avatar billede ladyhawke Novice
25. september 2002 - 14:28 Der er 20 kommentarer og
1 løsning

Event ved highlight i list ctrl?

Hvordan fanger jeg et event når en bruger har valgt en række (har valgt row select) i mit list view?

Jeg kan godt gøre det når der vælges med musen, men hvad med når man gør det med piletasterne? Det skal helst ikke være keyboard event, men et "highlight" event... Spdan at eventet jeg fanger er det der kommer uanset om man vælger rækken med mus eller taster...

Jeg bruger Visual C++ 6.0
Avatar billede jpk Nybegynder
25. september 2002 - 15:22 #1
Jeg mener ikke det umiddelbart kan lade sig gøre, jeg tror du er nødt til at fange fx WM_KEYDOWN og så tjekke hvilket element der er valgt...
Avatar billede jpk Nybegynder
25. september 2002 - 15:26 #2
Nej, jeg har lige tjekket, der sendes kun WM_KEYDOWN/WM_KEYUP messages ved valg med piletasterne, så desværre...
Avatar billede ladyhawke Novice
25. september 2002 - 15:29 #3
ØV :o/ Så må jeg jo lave begge dele...

Tak for hjælpen :o)
Avatar billede mbulow Nybegynder
25. september 2002 - 16:21 #4
Hmm... Der er jeg altså ikke helt sikker på at jeg er enig.

Jeg modtager en WM_NOTIFY message hver gang jeg aktiverer en række i mit listview...

Kig lidt nærmere på den her i dit MSDN:
LVN_ITEMACTIVATE

Den skulle kunne klare sagen... Jeg har da i hvert fald lavet en lille test-app der giver et *BIIP* hver gang jeg aktiverer en række... OGSÅ MED PILETASTERNE
Avatar billede mbulow Nybegynder
25. september 2002 - 16:24 #5
Der er godt nok dømt rent pladderkode, men her er min kildetekst:
(Det hele sker i WindowProc... WinMain opretter bare et window)
-----------------------------------------------------------------

#include <windows.h>
#include <commctrl.h>

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
    static INITCOMMONCONTROLSEX isex;
    static BOOL    bResult;
    static int iResult;
    static HWND    hMainWnd;
    static HWND hListViewWnd;
    static RECT rctMainWnd;
    static HINSTANCE hInstance;
    static LVCOLUMN    lvCol;
    static LVITEM lvItem;

    switch(uMsg){
        case WM_CREATE:
            hMainWnd = hWnd;
            hInstance = ((LPCREATESTRUCT)lParam)->hInstance;
            isex.dwICC = ICC_LISTVIEW_CLASSES;
            isex.dwSize = sizeof(isex);
            bResult = InitCommonControlsEx(&isex);
            if(bResult == FALSE){
                DestroyWindow(hWnd);
                break;
            }
            bResult = GetClientRect(hWnd, &rctMainWnd);
            if(bResult != TRUE){
                DestroyWindow(hWnd);
                break;
            }
            hListViewWnd = CreateWindowEx(LVS_EX_FULLROWSELECT, WC_LISTVIEW, "", LVS_REPORT | WS_CHILD | WS_VISIBLE, 0, 0, rctMainWnd.right - rctMainWnd.left, rctMainWnd.bottom - rctMainWnd.top, hMainWnd, (HMENU)187, hInstance, NULL);
            if(hListViewWnd == NULL){
                DestroyWindow(hWnd);
                break;
            }
            lvCol.cx = rctMainWnd.right - rctMainWnd.left;
            lvCol.mask = LVCF_TEXT | LVCF_WIDTH;
            lvCol.pszText = TEXT("Overskriften");
            iResult = ListView_InsertColumn(hListViewWnd, 0, &lvCol);
            if(iResult == -1){
                DestroyWindow(hWnd);
                break;
            }
            lvItem.mask = LVIF_TEXT;
            lvItem.pszText = "ABC";
            ListView_InsertItem(hListViewWnd, &lvItem);
            lvItem.pszText = "DEF";
            ListView_InsertItem(hListViewWnd, &lvItem);
            lvItem.pszText = "GHI";
            ListView_InsertItem(hListViewWnd, &lvItem);
            lvItem.pszText = "JKL";
            ListView_InsertItem(hListViewWnd, &lvItem);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        case WM_NOTIFY:
            if(((int)wParam) == 187){    //Den ID jeg gav min ListView-control
                MessageBeep(MB_OK);
            }
            break;
    }

    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd){
    HWND        hWnd;
    MSG            msg;
    TCHAR        szClassName[] = TEXT("ListViewTestClass");
    WNDCLASSEX    wcx;

    wcx.cbClsExtra = 0;
    wcx.cbSize = sizeof(wcx);
    wcx.cbWndExtra = 0;
    wcx.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wcx.hIconSm = NULL;
    wcx.hInstance = hInstance;
    wcx.lpfnWndProc = WindowProc;
    wcx.lpszClassName = szClassName;
    wcx.lpszMenuName = NULL;
    wcx.style = CS_HREDRAW | CS_VREDRAW;

    if(!RegisterClassEx(&wcx)){
        MessageBox(NULL, TEXT("An error occured while registering the window class"), TEXT("Error: WinMain - RegisterClassEx"), MB_ICONERROR);
        return 0;
    }

    hWnd = CreateWindow(szClassName, TEXT("Fun With ListViews"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);

    ShowWindow(hWnd, nShowCmd);
    UpdateWindow(hWnd);

    while(GetMessage(&msg, NULL, 0, 0)){
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}
Avatar billede ladyhawke Novice
25. september 2002 - 16:55 #6
KANON! Jeg kigge på det i morgen og hvis det kører får du lige lidt points i et nyt spørgsmål :o)
Avatar billede jpk Nybegynder
26. september 2002 - 08:49 #7
Det var pokkers!
Jeg har lige tjekket igen, jeg får altså kun 2 events når jeg skifter mellem item med piletasterne, nemlig WM_KEYDOWM og WM_KEYUP...
Avatar billede ladyhawke Novice
26. september 2002 - 08:53 #8
hmmm, Er jeg nødt til at oprette en WindowProc func.? Sådan én bruger jeg ikke lige nu... Hvis jeg skal, hvad skal den så, som minimum indeholde?

ListCtrl'en bliver initialiseret i initDialog og jeg ved ikke helt hvordan man fanger WM_NOTIFY events ellers...

Kan man bruge class wizard
Avatar billede ladyhawke Novice
26. september 2002 - 09:18 #9
Jeg kan godt finde LVN_ITEMACTIVATE, men det foregår vha. WM_NOTIFY så vidt jeg kan se... Indtil videre pusler jeg videre med keyboard events...
Avatar billede mbulow Nybegynder
26. september 2002 - 09:29 #10
Hmm... Det du har gang i nu, er det lavet i MFC eller???
Det er bare det eneste sted jeg mener at kunne genkende navnet initdialog, som OnInitDialog (og det at du ikke har en eller anden form for WindowProc eller DialogProc)... Eller er det rent Win32?

Hvis det er MFC du bruger, bruger du jo sikkert også CListView-klassen, som jeg ikke bruger... Men prøver da lige at kigge på noget MFC, kan jo være man kan lære noget :)

JPK: Ja så må jeg godt nok skylde sig et svar... Men har du prøvet at køre det lille program jeg har lavet? (Husk comctl32.lib)
Jeg bliver sgu næsten lidt tosset hvis ikke du hører nogle *BIIP*-lyde ;)
Avatar billede ladyhawke Novice
26. september 2002 - 09:43 #11
Jeg bruger MFC her og en CListCtrl. Og ja, det hedder OnInitDialog... :o)
Avatar billede jpk Nybegynder
26. september 2002 - 10:21 #12
Jo, det virker fint i ren Win32, men når jeg anvender MFC's wrapper, CListCtrl, modtager jeg ikke nogen notify-message...
Avatar billede ladyhawke Novice
26. september 2002 - 10:50 #13
Hmm... Det ser ud til at jeg må benytte keydown/up events til det. Det går også nok, men det er jo lidt træls :o)
Avatar billede jpk Nybegynder
26. september 2002 - 11:03 #14
Det lader til, at MFC deler events'ne op således at LVN_ITEMACTIVATE bliver til en WM_GETDLGCODE message...

mbulow >> du bruger jo ikke LVN_ITEMACTIVATE i dit eksempel, men fanger bare alle notifications til kontrollen! Kunne man forestille sig at der er nogle notifications der ikke skal reageres på..?

Jeg har lavet en nedarving af CListCtrl, kaldet CListCtrlEx, hvor jeg har overridet WindowProc således:

LRESULT CListCtrlEx::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
    // TODO: Add your specialized code here and/or call the base class
    TRACE("Message: %d - wParam: %d - lParam: %d\n", message, wParam, lParam);

    if(message == WM_GETDLGCODE && lParam)
    {
        #if (_WIN32_IE >= 0x0400)
            LPNMITEMACTIVATE lpnmia = (LPNMITEMACTIVATE)lParam;
        #else
            LPNMHDR lpnm = (LPNMHDR)lParam;
        #endif
    }

    return CListCtrl::WindowProc(message, wParam, lParam);
}

lpnmia er en pointer til en instans af NMITEMACTIVATE strukturen, der indeholder oplysninger om eventens afsender mm. Den kan du bruge til at reagere på valg med piletasterne.
Der er dog lige et par men'er:
- Hvis Internet Explorer er ældre end version 4.0 får du ikke oplysninger og hvilket item/subitem der er aktiveret.
- WM_GETDLGCODE sendes IKKE ved musetast...
Avatar billede mbulow Nybegynder
26. september 2002 - 11:15 #15
JPK: Ja nu jeg tænker over det kan du da godt have ret, men så fatter jeg bare ikke helt hvordan man skal kende forskel på om det er en WM_NOTIFY, som et resultat af en LVN_ITEMACTIVATED eller noget anden...



Meeeen... For at gøre forvirringen lidt større (måske), tror jeg jeg har fundet ud af hvordan problemet kan løses i MFC :)))

Jeg oprettede et MFC-Dialog-App. Tilføjede en ListControl, og fanger eventet LVN_ITEMCHANGED, med det her stykke kode... Den *BIIP*'er lysting løs, lige som Win32 versionen :))

En eller anden der har godt styr på MFC må gerne lige checke den igennem, for det er lidt en blanding af opfindsomhed og google-søgninger ;) For jeg fatter egentlig ikke ret meget af MFC endnu :)



void CTESTDlg::OnLvnItemchangedList1(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);

    // TODO: Add your control notification handler code here
    if(pNMLV->uNewState & LVIS_SELECTED && !(pNMLV->uOldState & LVIS_SELECTED))
        MessageBeep(MB_OK);

    *pResult = 0;
}
Avatar billede mbulow Nybegynder
26. september 2002 - 11:20 #16
UPS!!! Never mind... Den der kommentar om at kende forskel på WM_NOTIFY beskederne tror jeg lige jeg skynder mig at trække tilbage :)
Avatar billede jpk Nybegynder
26. september 2002 - 11:26 #17
Dovenskaben længe leve...
Jeg havde set eventen, men troede egentlig, udfra navnet LVN_ITEMCHANGED, at den kun blev sendt når der direkte blev ændret i et item...

Det er nu ikke nødvendigt at bruge reinterpret_cast, men det er selvfølgelig også lidt en smagssag...

LPNM_LISTVIEW pNMLV = (NM_LISTVIEW*)pNMHDR;
Avatar billede ladyhawke Novice
26. september 2002 - 11:31 #18
Det virker med følgende:

void CDlg::OnItemchangedListStatus(NMHDR* pNMHDR, LRESULT* pResult)
{
  NM_LISTVIEW* pNMListView = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
  // TODO: Add your control notification handler code here
      if(pNMListView->uNewState & LVIS_SELECTED && !(pNMListView->uOldState & LVIS_SELECTED))
      {
        MessageBeep(MB_OK);
      }

  *pResult = 0;
}
Avatar billede ladyhawke Novice
26. september 2002 - 11:32 #19
Jeg laver lige et spørgsmål så mbulow kan få points også :o)

Mange tak for hjælpen begge to !!!
Avatar billede mbulow Nybegynder
26. september 2002 - 11:35 #20
Narj :) Den lod jeg nu også bare stå som den var... Jeg har kun indsat if-sætningen og MessageBeep'et :)

PS!!! Jeg undskylder mange gange forviringen. Jeg lavede ikke mit feltarbejde ordentligt inden jeg kom med det jeg troede var en løsning.
JPK har ganske ret i at jeg fangede lidt for mange sjove ting og sager i min WM_NOTIFY. Jeg undersøgte lige sagen lidt nærmere, og fandt ud af at det overhoved ikke var LVN_ITEMACTIVATED der var interessant i forholdt til WM_NOTIFY eventet, men derimod LVN_ITEMCHANGED på samme måde som i MFC versionen.

/me knalder hovedet hårdt ind i væggen og efterlader buler i begge dele :/
Avatar billede jpk Nybegynder
26. september 2002 - 12:04 #21
hehe...

Godt arbejde mbulow, jeg lærte også noget af alt dette...
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester