С Новым годом! Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.59/32: Рейтинг темы: голосов - 32, средняя оценка - 4.59
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564

Процедура обработки дочернего окна (ListView и Edit)

24.04.2013, 18:07. Показов 6671. Ответов 19
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Для начала в кратце опишу что есть в моём проэкте.
1.Обработчик "главного окна":
C++
1
LRESULT EditProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-обрабатывает нажатия клавиш Элемента EditBox главного окна.
-РАБОТАЕТ ( почти, за исключением небольшой непонятной мне фичи, ловлю
C++
1
if(((LPNMHDR)lParam)->code == NM_DBLCLK)
забераю номера строки и столбца и создаю поверх ListView - EditBox, выходит всё нормально. Добавил поправку:
C++
1
case WM_KILLFOCUS:
, т.е. при потере фокуса - удаляется EditBox, оно конешно работает - но не совсем корректно, поясню: при двойном щелчке создаётся окно и получает фокус, если после получения фокуса пользователь передумал что то вводить и кликнул по какому то другому элементу - KILLFOCUS - уничтожает окно ввода, а если после появления окна ввода - нажать на него, то фокус теряется, но! окно не удаляется. Я так понимаю что окно, которое я создаю так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
case WM_NOTIFY:
        switch(LOWORD(wParam))
        {
        case ID_LISTVIEW:
            if(((LPNMHDR)lParam)->code == NM_DBLCLK)
            {
                hListView = GetDlgItem(hWnd, ID_LISTVIEW);
                gsi = ListView_GetNextItem(hListView, -1, LVNI_ALL | LVNI_SELECTED);
                char gc[10]="";
                int gi=0;
                if (gsi != -1)
                {
                    hComboCl = GetDlgItem(hWnd, ID_COMBOCL);
                    let = (int)SendMessage(hComboCl, CB_GETCURSEL, 0, 0);
                    if (let == 0)
                        MessageBox(hWnd, _T("Выберите название изменяемого элемента\nв списке 'Изменение'."), _T("Инструкция."), MB_OK);
                    if (let == 1)
                    {
                        DialogBox(hInst, MAKEINTRESOURCE(IDD_CHANGE), hWnd, Change);
                    }
                        //MessageBox(hWnd, _T("Изменения порядкового номера временно недоступно."), _T("Инструкция."), MB_OK);
                    if ((let > 1) && (let < 13))
                    {
                        if (cyl == 1)
                            ListView_Scroll(hListView,-800,0);
                        RECT subitemrect;
                        lcen = let-1;
                        gsu = ListView_GetSubItemRect(hListView,gsi,lcen,LVIR_BOUNDS,&subitemrect);
                        largura = subitemrect.right - subitemrect.left;
                        xp1 = subitemrect.left;
                        yp1 = subitemrect.top;
                        xp2 = largura;
                        yp2 = 16;
                        if ((let == 2) || (let == 4) || (let == 5) || (let == 7) || (let == 8) || (let == 12))
                        {
                            if ((let == 4) || (let == 12))
                                hEditEdt = CreateWindow(TEXT ("edit"), NULL , WS_CHILD | WS_BORDER, xp1+10, yp1+75, xp2, yp2, hWnd,(HMENU) (int)ID_EDITEDT, hInst, NULL);
                            if ((let == 2) || (let == 5) || (let == 7) || (let == 8))
                                hEditEdt = CreateWindow(TEXT ("edit"), NULL , WS_CHILD | WS_BORDER | ES_NUMBER, xp1+10, yp1+75, xp2, yp2, hWnd,(HMENU) (int)ID_EDITEDT, hInst, NULL);
 
                            HFONT hFontEd =CreateFont(12, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, "Arial");
                            SendMessage (hEditEdt, WM_SETFONT, WPARAM (hFontEd), TRUE);
                            DefEditProc = (WNDPROC)SetWindowLong(hEditEdt, GWL_WNDPROC, (long)EditProc);
                            SetFocus(hEditEdt);
                            ShowWindow(hEditEdt, SW_NORMAL);
                        }
                        if ((let == 3) || (let == 6) || (let == 9) || (let == 10) || (let == 11))
                        {
                            hComboEdt = CreateWindow(TEXT ("combobox"), NULL , WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST, xp1+10, yp1+75, xp2, yp2, hWnd,(HMENU) (int)ID_COMBOEDT, hInst, NULL);
                            // | CBS_DROPDOWNLIST
                            if(let == 6)
                            {
                                SendMessage(hComboEdt, CB_ADDSTRING, 0, (LPARAM) _T("Новая марка"));
                                SendMessage(hComboEdt, CB_SETCURSEL, 0, 0L);
                                for(int i=0; i<nl; i++)
                                {
                                    if(strcmp(mac[i].marka,cf)!=0)
                                    {
                                        strcpy(cf,mac[i].marka);
                                        SendMessageA(hComboEdt, CB_ADDSTRING, 0, (LPARAM)mac[i].marka);
                                    }
                                }
                            }
                            if(let == 9)
                            {
                                for(int i=0; i<5; i++)
                                {
                                    SendMessageA(hComboEdt, CB_ADDSTRING, 0, (LPARAM)Ttype[i]);
                                }
                                SendMessage(hComboEdt, CB_SETCURSEL, 0, 0L);
                            }
                            if(let == 10)
                            {
                                for(int i=0; i<2; i++)
                                {
                                    SendMessageA(hComboEdt, CB_ADDSTRING, 0, (LPARAM)Etype[i]);
                                }
                                SendMessage(hComboEdt, CB_SETCURSEL, 0, 0L);
                            }
                            if(let == 11)
                            {
                                for(int i=0; i<2; i++)
                                {
                                    SendMessageA(hComboEdt, CB_ADDSTRING, 0, (LPARAM)Ftype[i]);
                                }
                                SendMessage(hComboEdt, CB_SETCURSEL, 0, 0L);
                            }
                            HFONT hFontEd =CreateFont(12, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, "Arial");
                            SendMessage (hComboEdt, WM_SETFONT, WPARAM (hFontEd), TRUE);
                            DefEditProc = (WNDPROC)SetWindowLong(hComboEdt, GWL_WNDPROC, (long)EditProc);
                            SetFocus(hComboEdt);
                            ShowWindow(hComboEdt, SW_NORMAL);
                        }
                    }
                    if ((let > 12) && (let < 25))
                    {
                        ListView_Scroll(hListView,800,0);
                        RECT subitemrect;
                        lcen = let-1;
                        gsu = ListView_GetSubItemRect(hListView,gsi,lcen,LVIR_BOUNDS,&subitemrect);
                        largura = subitemrect.right - subitemrect.left;
                        xp1 = subitemrect.left;
                        yp1 = subitemrect.top;
                        xp2 = largura;
                        yp2 = 16;
                        hEditEdt = CreateWindow(TEXT ("edit"), NULL , WS_CHILD | WS_BORDER, xp1+10, yp1+75, xp2, yp2, hWnd,(HMENU) (int)ID_EDITEDT, hInst, NULL);
                        HFONT hFontEd =CreateFont(12, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, "Arial");
                        SendMessage (hEditEdt, WM_SETFONT, WPARAM (hFontEd), TRUE);
                        DefEditProc = (WNDPROC)SetWindowLong(hEditEdt, GWL_WNDPROC, (long)EditProc);
                        SetFocus(hEditEdt);
                        ShowWindow(hEditEdt, SW_NORMAL);
                    }
                }
            }
            break;
        }
        break;
В общем оно рисует новое окно не поверх формы ListView, а как то подругому...

Ладно, это отход от того что меня сейчас намного больше интересует.
Теперь ближе к сути:
Я создал в меню несколько полей и привязал Диалоги к ним. В одном из диалогов опять же есть форма ListView и так же создаётся EditBox на ней, и естественно опять же пишу новый обработчик к полю ввода. По какой то причине возникает следующяя ситуация: При двойном клике - создаётся(от координат мыши) EditBox, рисуется правильно. Далее я ввожу данные в появившееся поле ввода и нажимаю Enter, т.к. по задумке - после нажатия этой клавиши происходит сохранение результата, но однако нажатие Enter мне выводит сообщение о том, что окно не найдено или потеряно(если раскомментить строку if hEdit.. != NULL, то окажется что окна не существует, т.е. это он его не видит, но на самом деле оно есть!
Я не знаю чего я курил, но почему в основном окне обработчик работает, а в тут нет? - ведь я просто копировал обработчик, и изменения которые вносил - не могли повлиять на выход такой странной ошибки.
Возможно разгадка кроется в каких то полях, которые нужно переименовать (имеется ввиду hDlg или uMsg)...
Вот часть кода обработки и создания окна:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
case WM_NOTIFY:
        switch(LOWORD(wParam))
        {
        case ID_LISTOPADD:
            if(((LPNMHDR)lParam)->code == NM_DBLCLK)
            {
                hListOpAdd = GetDlgItem(hDadd, ID_LISTOPADD);
                int goadd = ListView_GetNextItem(hListOpAdd, -1, LVNI_ALL | LVNI_SELECTED);
                if (goadd != -1)
                {
                    lstrcpy(testadd,"Позиция скролла: ");
                    lvposadd = GetScrollPos(hListOpAdd, SB_HORZ);
                    itoa(lvposadd,tadd,10);
                    strcat(testadd,tadd);
                    lstrcat(testadd,"\nПозиция курсора: ");
                    GetCursorPos(&cur_pos);
                    sprintf(tadd, "%ld", cur_pos.x);
                    strcat(testadd,tadd);
                    lstrcat(testadd,"\nШирина колонок: ");
                    for(int i=0;i<16;i++)
                    {
                        //lvcadd[i] = ListView_GetSubItemRect(hListOpAdd,0,i,LVIR_BOUNDS,&subitemrect);
                        itoa(lvcadd[i],tadd,10);
                        strcat(testadd,tadd);
                        if(i<15)
                            lstrcat(testadd,", ");
                    }
                    lstrcat(testadd,"\nПозиция окна: ");
                    GetWindowRect(hDadd, &rcClient);
                    int SizeX = rcClient.left;
                    itoa(SizeX,tadd,10);
                    strcat(testadd,tadd);
                    lstrcat(testadd,"\nПозиции колонок: ");
                    for(int i=0;i<16;i++)
                    {
                        lvccadd=lvcpadd[i]+SizeX;
                        itoa(lvccadd,tadd,10);
                        strcat(testadd,tadd);
                        if(i<15)
                            lstrcat(testadd,", ");
                    }
                    lstrcat(testadd,"\nПозиция курсора соответствует ");
                    pxadd = cur_pos.x;
                    while(liadd < 16)
                    {
                        if((pxadd+lvposadd) < (lvcpadd[liadd]+SizeX))
                        {
                            liadd = 16+liadd;
                        }
                        else
                            liadd++;
                    }
                    if(liadd > 16)
                        liadd = liadd-16;
                    itoa(liadd,tadd,10);
                    strcat(testadd,tadd);
                    lstrcat(testadd," колонке.");
                    liadd = liadd-1;
                    //MessageBox(hDadd, testadd, _T("Позиции."), MB_OK);
                    int gsoadd = ListView_GetSubItemRect(hListOpAdd,goadd,liadd,LVIR_BOUNDS,&subitemrect);
                    int xp1 = subitemrect.left;
                    int yp1 = subitemrect.top;
                    int xp2 = subitemrect.right - subitemrect.left;
                    int yp2 = 16;
                    hEditLiOpAdd = CreateWindow(TEXT ("edit"), NULL , WS_CHILD | WS_BORDER | ES_NUMBER, xp1+10, yp1+40, xp2, yp2, hDadd,(HMENU) (int)ID_EDITLIOPADD, hInst, NULL);
                    HFONT hFontEa = CreateFont(12, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, "Arial");
                    SendMessage (hEditLiOpAdd, WM_SETFONT, WPARAM (hFontEa), TRUE);
                    DefEditProc = (WNDPROC)SetWindowLong(hEditLiOpAdd, GWL_WNDPROC, (long)AddProc);
                    
                    SetFocus(hEditLiOpAdd);
                    ShowWindow(hEditLiOpAdd, SW_NORMAL);
                }
            }
            break;
        }
        break;
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// Procedure for Additions box.
LRESULT AddProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    char addcp[25]="Пусто";
 
    switch (uMsg)
    {
    case WM_KILLFOCUS:
        {
            hEditLiOpAdd = GetDlgItem(hDadd, ID_EDITLIOPADD);
            hListOpAdd = GetDlgItem(hDadd, ID_LISTOPADD);
            DestroyWindow(hEditLiOpAdd);
            UpdateWindow(hListOpAdd);
            //InvalidateRect(hDadd, NULL, TRUE);
        }
        break;
    case WM_GETDLGCODE:
        {
            if( wParam == 27 )
            {
                hEditLiOpAdd = GetDlgItem(hDadd, ID_EDITLIOPADD);
                if (hEditLiOpAdd != NULL)
                {
                    DestroyWindow(hEditLiOpAdd);
                    MessageBox(hwnd, "Удалено.", _T("Успех!"), MB_OK);
                }
                else
                    MessageBox(hwnd, "Окно не найдено.", _T("Ошибка!"), MB_OK);
            }
            if( wParam == 13 )
            {
                hEditLiOpAdd = GetDlgItem(hDadd, ID_EDITLIOPADD);
                GetDlgItemText(hDadd, ID_EDITLIOPADD, addcp, 25);
                //if (hEditLiOpAdd != NULL)
                if (strlen(addcp) != 0)
                {
                    hListOpAdd = GetDlgItem(hDadd, ID_LISTOPADD);
                    //GetDlgItemText(hDadd, ID_EDITLIOPADD, addcp, 15);
                    if(strlen(addcp) == 0)
                    {
                        MessageBox(hwnd, "Ввод пустой строки невозможен./nЕсли данных нет, поставьте прочерк '-' *(знак минус)", _T("Ошибка ввода!"), MB_OK);
                        DestroyWindow(hEditLiOpAdd);
                        return 0;
                    }
                    DestroyWindow(hEditLiOpAdd);
                    UpdateWindow(hListOpAdd);
                    InvalidateRect(hDadd, NULL, TRUE);
                    MessageBox(hwnd, addcp, _T("Данные приняты."), MB_OK);
                }
                else
                    MessageBox(hwnd, addcp, _T("Данные потеряны."), MB_OK);
            }
            if( (wParam != 13) && (wParam != 27) )
            {
                return CallWindowProc(DefEditProc, hwnd, uMsg, wParam, lParam);
            }
        }
        break;
        default:
           return CallWindowProc(DefEditProc, hwnd, uMsg, wParam, lParam);
    }
    return FALSE;
}
Прошу помощи =)

Добавлено через 1 час 56 минут
Ещё поковырялся, и немного продвинулся, хотя непонятно куда =)
Поменял немного код в обработчике, при этом происходят следующие события:
1. Т.к. определено
C++
1
char addcp[25]="Пусто";
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
if( wParam == 13 )
            {
                hEditLiOpAdd = GetDlgItem(hDadd, ID_EDITLIOPADD);
                hListOpAdd = GetDlgItem(hDadd, ID_LISTOPADD);
 
                if (hEditLiOpAdd != NULL)
                {
                    GetDlgItemText(hDadd, ID_EDITLIOPADD, cpadd, 25);
                    if(strlen(cpadd) == 0)
                    {
                        MessageBox(hwnd, "Ввод пустой строки невозможен./nЕсли данных нет, поставьте прочерк '-' *(знак минус)", _T("Ошибка ввода!"), MB_OK);
                        DestroyWindow(hEditLiOpAdd);
                        UpdateWindow(hListOpAdd);
                        return 0;
                    }
                    DestroyWindow(hEditLiOpAdd);
                    UpdateWindow(hListOpAdd);
                    InvalidateRect(hDadd, NULL, TRUE);
                    MessageBox(hwnd, cpadd, _T("Данные приняты."), MB_OK);
                }
                else
                    MessageBox(hwnd, cpadd, _T("Данные потеряны."), MB_OK);
            }
В этом случае - при вводе данных выходит сообщение о потере данных,т.е. hEditLiOpAdd == NULL, при этом cpadd - остаётся неизменной.
Если же закоментировать строку :
C++
1
hEditLiOpAdd = GetDlgItem(hDadd, ID_EDITLIOPADD);
то в итоге выводится сообщение о пустой строке... т.е. hEditLiOpAdd != NULL (что уже прогресс), но каким то образом переменная "char cpadd[25]" опустошается, т.е. при вызове функции GetDlgItemText - поступает пустая строка (очень странно, ведь я ввожу туда данные и они отображаются, но в переменную не заносятся)...

Ну же я чувствую разгадка уже близко, помогите ^ ^
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
24.04.2013, 18:07
Ответы с готовыми решениями:

ListView дочернего окна
Здравствуйте, уважаемые программисты! Суть проблемы такая: Есть дочернее окно чужой программы, в котором находятся Edit и ListView (а...

У дочернего окна не доступен Edit
Всем привет,нужна помощь. Вообщем недавно мне тут помогли с созданием дочернего окна.Вот код: #include &lt;windows.h&gt; #include...

Вставить текстовые данные в Edit дочернего окна стороннего приложения
В общем имеется строковая переменная и окно стороннего приложения, имеющее дочернее окно класса Edit (класс узнал экспериментально с...

19
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
07.05.2013, 14:05  [ТС]
До сих пор актуально, дайте хотяб зацепку... А то я даже не знаю на что подумать... Ведь в главном окне всё(почти) пучком, а в дочернем окне - нет =(
0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
13.05.2013, 07:50  [ТС]
Прближение было найдено, однако ещё не понятно как решить теперь задачу.

Стандартный обработчик в IntMain я заменил так:
C++
1
( (!IsDialogMessage(hWnd,&msg)) && (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) )
И я так понимаю что это не будет работать в окнах открытых из меню...
Может кто скажет как преодолеть данный барьер, т.к. я конешно пойду читать что такое IsDialogMessage... но боюсь не осилю до конца, т.к. точно мсдн пока что не могу перевести...

Добавлено через 21 минуту
Походу я понял =)

C++
1
(!IsDialogMessage(hWnd,&msg))
Обрабатывает только сообщения окна c дескриптором hWnd, для обработки других окон(а лучше всех) - нужно взять текущий дескриптор.. =)

Добавлено через 33 минуты
C++
1
2
3
4
5
6
7
8
while (GetMessage(&msg, NULL, 0, 0))
    {
        if ( (!IsDialogMessage(hWnd,&msg)) && (!IsDialogMessage(hDadd,&msg)) && (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) )
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
Не работает почему то... Естественно hDadd объявлен в глобальных.

Добавлено через 39 минут
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
if( wParam == 13 )
            {
                hEditLiOpAdd = GetDlgItem(hDadd, ID_EDITLIOPADD);
                hListOpAdd = GetDlgItem(hDadd, ID_LISTOPADD);
 
                if (hEditLiOpAdd != NULL)
                {
                    GetDlgItemText(hDadd, ID_EDITLIOPADD, cpadd, 25);
                    if(strlen(cpadd) == 0)
                    {
                        MessageBox(hwnd, "Ввод пустой строки невозможен./nЕсли данных нет, поставьте прочерк '-' *(знак минус)", _T("Ошибка ввода!"), MB_OK);
                        DestroyWindow(hEditLiOpAdd);
                        UpdateWindow(hListOpAdd);
                        return 0;
                    }
                    DestroyWindow(hEditLiOpAdd);
                    UpdateWindow(hListOpAdd);
                    InvalidateRect(hDadd, NULL, TRUE);
                    MessageBox(hwnd, cpadd, _T("Данные приняты."), MB_OK);
                }
                else
                    MessageBox(hwnd, cpadd, _T("Данные потеряны."), MB_OK);
            }
Даже с учётом добавленной строки :
C++
1
(!IsDialogMessage(hDadd,&msg))
всё равно не работает... Пишет что "Даные потеряны" - т.е. не видит EditBox, хотя символы в EditBox вводятся, и на нажатие <Enter> он реагирует, правада по непонятным мне причинам - не хочет читать то что есть в EditBoxe...
Где hDadd - является дескриптором родительского меню (не основного, а открытого из меню).

Добавлено через 12 минут
... Может какие то флажки нужно включить в самом диалоговом окне, в котором расположен EditBox?... Я создавал его просто New Dialog и менял там только название окна...

Добавлено через 9 часов 59 минут
Модифицировал обработчик, дабы понять где проблема...
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
case WM_KILLFOCUS:
        {
            hListOpAdd = GetDlgItem(hDadd, ID_LISTOPADD);
            hEditLiOpAdd = GetDlgItem(hDadd, ID_EDITLIOPADD);
            if (hEditLiOpAdd != NULL)
            {
                DestroyWindow(hEditLiOpAdd);
                UpdateWindow(hListOpAdd);
                MessageBox(hwap, "KILLFOCUS!", _T("Удалено!"), MB_OK);
            }
            else
                MessageBox(hwap, "KILLFOCUS!", _T("Окно не найденно."), MB_OK);
        }
        break;
В итоге - теперь, как и прежде после появления окна, ввода в него данных и нажатия на клавишу ENTER появляется сообщение "Окно не найдено" - от WM_GETDLGCODE. Но теперь, что меня поразило... До этого сообщения, появляется сообщение "KILLFOCUS" - "Окно не найдено"... Т.е. WM_KILLFOCUS срабатывает раньше чем WM_GETDLGCODE... капец, уже месяц не могу доделать, пойду пить йад =(
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33371 / 21497 / 8234
Регистрация: 22.10.2011
Сообщений: 36,893
Записей в блоге: 12
13.05.2013, 08:25
Если б ты собрал минимальное приложение (но полностью, а не по кусочкам!!!), иллюстрирующее проблему, давно бы ее уже нашли. Мне, скажем, просто лень собирать всё, что здесь написано в один проект, да еще и догадываться, как ты связал то, о чем тут не упомянул, поэтому даже читать не стал это всё. Будет код, который можно откомпилировать, запустить и увидеть проблему - посмотрю...
0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
13.05.2013, 08:33  [ТС]
Возможно проблема в не правильном вызове функции SetWindowLong...
Я на сколько понимаю МСДН, то существуют 2 флага обработки(субклассинга) - GWL_WNDPROC и DWL_DLGPROC.
Диалог, на котором создан ListView и EditBox - я понимаю что для него (если бы надо было) нужно было бы пользоваться DWL_DLGPROC...
Но ведь у меня окно на диалоге, и тогда получается нужно пользоваться GWL_WNDPROC ?... Или нужно совместить? ~ ~
В инете к сожалению на WinApi флаг DWL_DLGPROC очень мало не то что примеров, а даже просто информации...
0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
13.05.2013, 10:50  [ТС]
Выкладываю проэкт, скомпилирован на VC++ 2005
Вложения
Тип файла: rar SubclassExample.rar (4.32 Мб, 66 просмотров)
0
267 / 189 / 33
Регистрация: 15.01.2011
Сообщений: 681
13.05.2013, 13:36
для начала
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
LRESULT AddProc(HWND hwap, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    int i = 0; /// для номера ошибки
    switch (uMsg)
    {
    case WM_KILLFOCUS:
        {
            hListOpAdd = GetDlgItem(hDadd, ID_LISTOPADD);
            if(!hListOpAdd)
                i = GetLastError();                          // error 1400 , ???
            hEditLiOpAdd = GetDlgItem(hDadd, ID_EDITLIOPADD);
.....
}
+ Почему сообщение WM_KILLFOCUS не подходит для проверки правильности ввода прямо по твоей теме )
1
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
13.05.2013, 15:02  [ТС]
ssXXss, спасибо! Ваш совет по использованию этого СУПЕРСКОГО метода на главную страницу бы вывесить, я раньше и не знал что такое есть... (уже скопировал себе все страницы ошибок кодов на комп в ворд, считаю каждый должен иметь).
Но всё же моя проблема осталась актуальной, т.к. углубляться в синтаксис использования данного метода только предстоит. Кстати уже нашёл какую то странность:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
case WM_KILLFOCUS:
        {
            //hListOpAdd = GetDlgItem(hDadd, ID_LISTOPADD);
            if(!hListOpAdd)
            {
                ErCode = GetLastError();
                if(ErCode != 0)
                {
                    itoa(ErCode,CErCode,10);
                    MessageBox(hwap, CErCode, "! ERROR MESSAGE !", MB_OK);
                }
            }
            //hEditLiOpAdd = GetDlgItem(hDadd, ID_EDITLIOPADD);
            if(!hEditLiOpAdd)
            {
                ErCode = GetLastError();
                if(ErCode != 0)
                {
                    itoa(ErCode,CErCode,10);
                    MessageBox(hwap, CErCode, "! ERROR MESSAGE !", MB_OK);
                }
            }
            if (hEditLiOpAdd != NULL)
            {
                DestroyWindow(hEditLiOpAdd);
                UpdateWindow(hListOpAdd);
                MessageBox(hwap, "KILLFOCUS!", _T("Удалено!"), MB_OK);
            }
            else
                MessageBox(hwap, "KILLFOCUS!", _T("Окно не найденно."), MB_OK);
        }
        break;
После "закоменчивания" ошибка перестала выскакивать, но ЛОЛ, только я кликаю дабы пропал фокус, сразу вылезает "окно не найдено", хотя ранее на ошибку была проверка и ничего не дала (т.е. был 0). Я же правильно понимаю :
C++
1
if (hEditLiOpAdd != NULL)
тоже самое что и
C++
1
if(!hEditLiOpAdd)
..?
Ладно, пойду дальше искать ошибки, кровь из носу, нужно исправить баг.

Кстати, а что же вы не описали в статье решение данной проблемы с исп. KILLFOCUS ? Я так понимаю решение - брать все активные окна и перебирать их на нужность их присутствия.. и наверно делать это надо каждый раз, когда пользователь что то делает (двигает мышкой ли, нажимает на клавиши..)(естественно пока приложение активно).

Добавлено через 15 минут
C++
1
2
3
4
5
6
7
8
9
if(!GetDlgItemText(hDadd, ID_EDITLIOPADD, cpadd, 50))
                    {
                        ErCode = GetLastError();
                        if(ErCode != 0)
                        {
                            itoa(ErCode,CErCode,10);
                            MessageBox(hwap, CErCode, "! ERROR MESSAGE !", MB_OK);
                        }
                    }
Показывает 1400... Ошибка хэндла окна, он походу не видит hDadd, по видимому ошибка всё же в том что я не правильно делаю сабклассинг для окон, находящихся в диалоге. К сожалению так уже в гугле искал, но ничего так и не нашёл или нету просто на русском )))

Добавлено через 2 минуты
Думал, думал над тем что сказал, у увидел "GetDlgItemText" - так тут же DLG, значит сабклассинг надо через DWL_DLGPROC флаг делать, правда я уже пробовал, но не помогло, пойду дальше пробовать)))
0
267 / 189 / 33
Регистрация: 15.01.2011
Сообщений: 681
13.05.2013, 17:13
мне чужой славы не надо )) статья не моя, просто как то сам столкнулся почти с подобным и сохранилась ссылка.
0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
14.05.2013, 13:48  [ТС]
Цитата Сообщение от ssXXss Посмотреть сообщение
мне чужой славы не надо )) статья не моя, просто как то сам столкнулся почти с подобным и сохранилась ссылка.
Да тут дело не в славе, а в реально полезной вещи... Хотя мне не особо помогла потому как ошибка видимо в том что процедура обработчика должна идти через DWL_DLGPROC, а в интернете то что выкладывается по этому поводу - сплошной мрак, криво и не работает... Уже что тока не перепробовал, походу, если не сделаю так, придётся делать очень тупо через отдельное диалоговое окно, жуть, за такое руки оторвать, получится не программинг, а *** на постном масле)))

Добавлено через 18 часов 34 минуты
Может всё же кто то подскажет, файл выложен в посте № 6.
Из кода - работа LV с эдитом (эдит появляется после двойного щелчка на строке в текущем положении курсора) в основном окне - нормальная, обрабатывается как WM_KILLFOCUS, так и при вводе символов и нажатии ENTER - выводится окошко с введёнными символами.

Проблема в LV из меню... там хоть эдит и появляется, и вводятся туда данные, но они не сохраняются. KILLFOCUS глючит...

Ну что тут нет никого кто мог бы помочь?...
0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
16.05.2013, 15:44  [ТС]
До сих пор актуально и тишина =)

П.С. надеюсь поднимая топик я не нарушаю никаких правил пользования форумом...
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33371 / 21497 / 8234
Регистрация: 22.10.2011
Сообщений: 36,893
Записей в блоге: 12
17.05.2013, 14:10
Цитата Сообщение от Izual Посмотреть сообщение
Проблема в LV из меню...
Проблема начинается уже с того, что у тебя глобальная переменная hDadd не инициализируется нигде и ничем, и при попытке изнутри AddProc обратиться к ней с целью:
C++
1
2
hListOpAdd = GetDlgItem(hDadd, ID_LISTOPADD);
hEditLiOpAdd = GetDlgItem(hDadd, ID_EDITLIOPADD);
, оба эти хендла совершенно закономерно оказываются пустыми...
0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
17.05.2013, 15:21  [ТС]
Цитата Сообщение от UI Посмотреть сообщение
Проблема начинается уже с того, что у тебя глобальная переменная hDadd не инициализируется нигде и ничем, и при попытке изнутри AddProc обратиться к ней с целью:
C++
1
2
hListOpAdd = GetDlgItem(hDadd, ID_LISTOPADD);
hEditLiOpAdd = GetDlgItem(hDadd, ID_EDITLIOPADD);
, оба эти хендла совершенно закономерно оказываются пустыми...
C++
1
HWND hDadd;
Объявлена в глобальных.

C++
1
INT_PTR CALLBACK Additions(HWND hDadd, UINT message, WPARAM wParam, LPARAM lParam)
hDadd - хэндл окна, как можно "инициализировать" его?.. Окно же было создано, в параметре хэндла указано.. Значит проинициализированно?... Или не так? Поясните пожалуйста сам факт...
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33371 / 21497 / 8234
Регистрация: 22.10.2011
Сообщений: 36,893
Записей в блоге: 12
17.05.2013, 16:36
Цитата Сообщение от Izual Посмотреть сообщение
Окно же было создано, в параметре хэндла указано
Это функция диалогового окна. Внутри нее - обращайся к параметру hDadd, сколько влезет. Но как только попытаешься обратиться извне (я показал, где, поставь точку останова
C++
1
2
3
4
5
6
7
8
9
// Procedure for Additions box.
LRESULT AddProc(HWND hwap, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_KILLFOCUS:
        {
            hListOpAdd = GetDlgItem(hDaddTest, ID_LISTOPADD); // <--- Вот на эту строку
            hEditLiOpAdd = GetDlgItem(hDaddTest, ID_EDITLIOPADD);
, и посмотри, чему равно значение глобальной переменной hDadd) - облом...

Цитата Сообщение от Izual Посмотреть сообщение
как можно "инициализировать" его?
В момент создания диалогового окна (да, именно после получения WM_INITDIALOG) первое что делается - это
C++
1
2
3
4
5
case WM_INITDIALOG:
   {
      hDaddTest = hDadd; // Я поменял название глобальной переменной на hDaddTest
      hListOpAdd = CreateWindow(WC_LISTVIEW, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | LVS_REPORT, 
         5, 5, 150, 150, hDadd,(HMENU) ID_LISTOPADD, hInst, NULL);
, теперь отовсюду можно обращаться к этой глобальной переменной, она содержит правильный хэндл диалога.

Это была первая ошибка. Вторая: в момент обработки WM_GETDLGCODE внутри
C++
1
2
// Procedure for Additions box.
LRESULT AddProc(HWND hwap, UINT uMsg, WPARAM wParam, LPARAM lParam)
, что такое hwap по-твоему? Хэндл чего? Если ты думал, что это хэндл главного окна приложения - то ошибаешься. Это тот самый EDIT, который ты создал на диалоговом окне. И как ты передаешь его в MessageBox первым параметром, спрашивается? Передавай что-нибудь другое. Или вообще NULL, будешь получать все MessageBox-ы, на которые рассчитываешь
0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
18.05.2013, 15:45  [ТС]
что такое hwap по-твоему? Хэндл чего?
Это хэндл процесса наверно... Я просто делал это исходя из того, что в заменённой процедуре EditProc - всё работает, а хэндл там не hWnd - т.е. главного окна, а hwnd - т.е. совсем другой...
Мессаги выводились и с hwap хзндлом.

Теперь поменял как ты сказал глобальну переменную hDadd на hDaddTest - и вообще ничего не работает. ~ ~ Эдит окно создаётся, но не реагирует по AddProc на нажатие Enter и Esc, а обрабатывает как стандартный обработчик, после нажатия Enter - окно просто исчезает... А Esc - выходит из Диалогового окна вообще.
Я не понимаю что ты мне написал, стало помоему ещё хуже ~ ~

Добавлено через 9 минут
Заменил в процедуре обработки hwap на hDaddTest - процедура опять заработала, но куча ERROR, и текст так и не вывелся =(
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33371 / 21497 / 8234
Регистрация: 22.10.2011
Сообщений: 36,893
Записей в блоге: 12
18.05.2013, 15:51
VS не держу, компилировал в Code::Blocks, заодно сделал Юникодный проект, вот результат:
subclass_example.zip

Что на этот раз не так?
0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
18.05.2013, 21:43  [ТС]
У вас то я смотрю всё работает =) А вот у меня почему то нет... Ругается на 1421 ошибку через ERROR, типа неправильный ид там ID_LISTOPADD... Но компилятор не ругается.
Что то я не так сделал как вы сказали... Сейчас буду разбираться...
И кстати, я что то не понял, а к чему вы сказали что "hwap" не канает, а сами же его оставили)))
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33371 / 21497 / 8234
Регистрация: 22.10.2011
Сообщений: 36,893
Записей в блоге: 12
19.05.2013, 02:38
Цитата Сообщение от Izual Посмотреть сообщение
И кстати, я что то не понял, а к чему вы сказали что "hwap" не канает, а сами же его оставили)))
А ты внимательно смотрел, где именно я его оставил? Только в вызовах CallWindowProc(DefEditProc, ..., тут я обязан оставить именно те параметры, которые были переданы в подменённую функцию окна, следовательно, раз был передан hwap - я должен именно его передать дефолтному обработчику. Кроме этих 2-х вызовов у меня нигде hwap не используется.
0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
19.05.2013, 06:55  [ТС]
Так что же такое hwap? Хэндл процедуры? Или что то другое?...
Вообще спасибо что помог... "С горем пополам" как говорится)))
Но всё же я особо не понял что именно произошло... А по хорошему именно "детали" и являются первопричиной, до которой всё же хочется докопаться, т.к. результат работы программы хоть и хорошо, но не главное, т.к. работает временно... В следующий раз опять сделаю ошибку, т.к. сути то я и не уловил)
И ещё, я что то не догнал фразу:
Или вообще NULL, будешь получать все MessageBox-ы, на которые рассчитываешь
Как же можно ноль передавать? Ноль - это грубо говоря "не используется" или "по умолчанию"... а что именно тогда получится по умолчанию?

Вообще, конешно програминг это очень занимательно, но очень многое в этом деле ну просто приходится "как об стену лбом" и либо нужен хороший лектор, который разжуёт с азов, либо надеяться на удачу - что не разумно.

Добавлено через 5 минут
а что именно тогда получится по умолчанию?
Даже наверно не так, т.к. это обстрактно. Ведь ф-я Message Box - идёт в процедуру обработки приложения в место GetMessage. Т.е. получая какое либо сообщение, программа берёт место от куда оно пришло и соответственно поставленную задачу. А если передавать NULL, то получится уже как то непонятно, что и от куда пришло - значит косяк, и приведёт потом к не предсказуемым последствиям, которые так сказать не были предусмотрены.
Я правильно разсуждаю? =)
0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
26.03.2014, 14:40  [ТС]
Так, предыдущие ньюансы были решены. Всем спасибо за помощь. Пришло время идти дальше в теме сабклассинга.

На этот раз я решил оптимизировать сабклассированную процедуру, т.к. элементов для сабклассирования очень много, то решил сделать одну функцию для сабклассинга всех элементов, но возникла пара вопросов.
1. Если я буду сабклассировать несколько разных элементов(например EditBox и ComboBox), то ни чего страшного не произойдёт, если я впишу все Case которые нужны для каждого типа элементов?(т.е. в одной процедуре будут и EN_CHANGE и CBN_SELCHANGE)
2. Т.к. я буду описывать все notify, то я так понимаю что ежели мне не понадобится изменять стандартую обработку, а в коде будет этот case, то он выполнится, а стандартной - не будет.
C++
1
2
3
4
case WM_KILLFOCUS:
        {
        }
        break;
Так я подумал, значит создам if/else, основанный на том нужно мне стандартно обрабатывать сообщение или нет. В следствии этого вопрос, если я сделаю так как показал ниже, будет ли это правильным?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
case WM_KILLFOCUS:
        {
if(N==TRUE)
{
//выполняется собственный код
}
else
{
//нужно чтоб выполнился код соответствующий стандартной обработке
return CallWindowProc(DefEditProc, hwnd, uMsg, wParam, lParam);
}
        }
        break;
3. Т.к. некоторые элементы будут "параллельно" обрабатываться, то мне необходимо будет брать хэндл элемента, пославшего сообщение. Как его взять при каждом вызове?(и наверно даже "где?", т.к. мысли идут в обработчик в самом MAIN, хотя хотелось бы в самой оконной функции его взять)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
26.03.2014, 14:40
Помогаю со студенческими работами здесь

Оконная процедура дочернего окна - обработчик кнопки "Close" не работает
Здравствуйте! В своей программе создала дочернее окно, и создала оконную процедуру для него. А в нем написала обработчик кнопки...

Как получить размеры клиентской области окна-родителя в функции дочернего окна?
задание такое: имеется дочернее окно,которое &quot;убегает&quot; от курсора мыши в пределах родительского окна. я создала главное окно,и дочернее,...

При открытии дочернего окна, отображаются формы и кнопки с основного окна; как исправить?
при открытии дочернего окна, отображаются формы и кнопки с основного окна, как можно исправить? ...

Позиционирование дочернего окна относительно элемента главного окна
Всем привет. Подскажите пожалуйста, как можно сделать. У меня есть главное окно, на котором условно говоря расположен textbox, также у меня...

Закрытие дочернего окна приводит к закрытию основного окна
Суть задания &quot;После нажатия левой кнопки мышки в области окна в левом углу окна создать временное окно размером в чверть основного окна....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Изучаю kubernetes
lagorue 13.01.2026
А пригодятся-ли мне знания kubernetes в России?
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru