Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 16, средняя оценка - 4.81
Gepar
1177 / 533 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
#1

"Поймать" сообщение от LISTBOX - C++

09.11.2011, 11:40. Просмотров 2109. Ответов 42
Метки нет (Все метки)

Рассматриваю тут пример в книге и вот почему-то он у меня срабатывать не хочет - не могу изменять масштаб в диалоговом окне так как он тупо вообще не выбирается, может стиля какого не хватает при создании диалогового окна, или ещё чего, подскажите пожалуйста.
Собственно main.h (константы и объявления функций)

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#define MI_OPEN 101
#define MI_EXIT 102
#define MI_SETTINGS 103
#define ID_DOTS 201
#define ID_CURVE 202
#define ID_SCALE 203
 
//определение нового типа GrapgModes
enum GraphModes{DOTS=ID_DOTS,CURVE=ID_CURVE};
 
//прототипы функций для главного окна
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
void OnCommand(HWND,int,HWND,UINT);
void OnPaint(HWND);
void OnDestroy(HWND);
 
//прототипы функций для диалогового окна
BOOL CALLBACK DlgProc(HWND,UINT,WPARAM,LPARAM);
BOOL DlgOnInitDialog(HWND,HWND,LPARAM);
void DlgOnCommand(HWND,int,HWND,UINT);
main.rc (диалоговое окно и меню, возможно в диалоговом окне в элементе LISTBOX какраз и есть ошибка)
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
#include "main.h"
#include <windows.h>
 
Main MENU
{
    POPUP "&Файл"
    {
        MENUITEM "&Открыть...",MI_OPEN
        MENUITEM "&Режимы...",MI_SETTINGS
        MENUITEM SEPARATOR
        MENUITEM "&Выход",MI_EXIT
    }
}
 
SettingsDlg DIALOG 150,0,125,80
STYLE WS_VISIBLE | WS_SYSMENU | WS_POPUP
CAPTION "Режимы вывода данных"
{
    CONTROL "Вид",-1,"BUTTON",BS_GROUPBOX,10,10,65,45
    CONTROL "Точки",ID_DOTS,"BUTTON",BS_AUTORADIOBUTTON,15,20,45,14
    CONTROL "Огибающая",ID_CURVE,"BUTTON",BS_AUTORADIOBUTTON,15,35,55,14
    CONTROL "",ID_SCALE,"LISTBOX",BS_NOTIFY|WS_VSCROLL|WS_BORDER,85,15,30,50
    CONTROL "Масштаб",-1,"STATIC",SS_LEFT,85,3,40,10
    CONTROL "Закрыть",IDOK,"BUTTON",BS_PUSHBUTTON,25,60,40,14
}
ну и главный файл
main.cpp
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#include <windows.h>
#include <windowsx.h>
#include "main.h"
 
char szClassName[]="MainWindow";
char szTitle[]="Программа 6-5";
char szFile[128];//для спецификации выбранного файла
short nBuf[500];//Буфер для чтения массива из файла
BOOL bDataOK=FALSE;//Если TRUE - данные прочитаны в буфер nBuf
HINSTANCE hI;//дескриптор приложения
short nBufScaled[500];//Буфер для масштабированного массива
int nScales[8]={200,175,150,125,100,75,50,25};//Массив масштабов
int nScaleIndex=4;//Текущее (и начальное) значение индекса в массиве масштабов
float nCurrentScales=1;//текущее (и начальное) значение масштаба
HWND hSettingsBox;//дескриптор немодального диалога
GraphModes Mode=DOTS;//режим наблюдения и его начальное значение
HPEN hPen;//дескриптор нового пера
 
int WINAPI WinMain(HINSTANCE hInst,HINSTANCE,LPSTR,int)
{
    MSG msg;
    hI=hInst;
    WNDCLASS wc;
     ZeroMemory(&wc,sizeof(wc));
     wc.style=CS_VREDRAW;
     wc.lpfnWndProc=WndProc;
     wc.hInstance=hInst;
     wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);
     wc.hCursor=LoadCursor(NULL,IDC_ARROW);
     wc.hbrBackground=GetStockBrush(WHITE_BRUSH);
     wc.lpszMenuName="Main";
     wc.lpszClassName=szClassName;
    RegisterClass(&wc);
 
    HWND hwnd=CreateWindow(szClassName,szTitle,WS_OVERLAPPEDWINDOW,
                           0,0,600,400,HWND_DESKTOP,NULL,hInst,NULL);
    ShowWindow(hwnd,SW_SHOWNORMAL);
    hPen=CreatePen(PS_SOLID,1,RGB(0,0,255));
    while(GetMessage(&msg,NULL,0,0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
 
    return 0;
}
 
 
LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
        HANDLE_MSG(hwnd,WM_COMMAND,OnCommand);
        HANDLE_MSG(hwnd,WM_PAINT,OnPaint);
        HANDLE_MSG(hwnd,WM_DESTROY,OnDestroy);
 
        default:
         return DefWindowProc(hwnd,msg,wParam,lParam);
    }
}
 
 
//функция обработки сообщения WM_COMMAND от меню
void OnCommand(HWND hwnd, int id, HWND, UINT)
{
    OPENFILENAME ofn;//структура для функции GetOpenFileName
    char szFilter[]="Файлы данных (*:DAT)\0*.dat\0Все файлы(*.*)\0*.*\0";
    DWORD nCnt;//Вспомогательная переменная для файловых операций
 
    switch (id)
    {
        case MI_OPEN:
         ZeroMemory(&ofn,sizeof(OPENFILENAME));
         ofn.lStructSize=sizeof(OPENFILENAME);//размер структуры
         ofn.hwndOwner=hwnd;//дескриптор окна-владельца диалога
         ofn.lpstrFilter=szFilter;//строка с шаблонами имен искомых файлов
         ofn.lpstrFile=szFile;//буфер для имени файла
         ofn.nMaxFile=sizeof(szFile);//его размер
         ofn.Flags=OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST;
         if(GetOpenFileName(&ofn))
         {
             HANDLE hFile=CreateFile(szFile,GENERIC_READ,0,0,OPEN_EXISTING,0,NULL);
             if(hFile==INVALID_HANDLE_VALUE) break;//если не удалось открыть файл
             ReadFile(hFile,nBuf,2*500,&nCnt,NULL);//чтение из файла
             CloseHandle(hFile);
             bDataOK=TRUE;//данные имеются, можно выводить
 
             for(int i=0;i<500;i++)//выполним начальное масштабирование спектра
              nBufScaled[i]=nBuf[i]*nCurrentScales;
             InvalidateRect(hwnd,NULL,TRUE);//инициируем WM_PAINT
             break;
         }
 
         else
          break;//если файл не выбран
 
        case MI_EXIT:
         DestroyWindow(hwnd);
         break;
 
        case MI_SETTINGS:
         if(hSettingsBox==NULL)//если диалог ещё не открыт, создадим его
          hSettingsBox=CreateDialog(hI,"SettingsDlg",hwnd,DlgProc);
         break;
    }
}
 
//функция обработки сообщения WM_PAINT
void OnPaint(HWND hwnd)
{
    RECT r;
    PAINTSTRUCT ps;
    HDC hdc=BeginPaint(hwnd,&ps);
     HPEN hOldPen=SelectPen(hdc,hPen);
     GetClientRect(hwnd,&r);//получение координат рабочей области
     if(bDataOK)
     {
         switch(Mode)
         {
             case DOTS:
             {
                 for(int i=0;i<500;i++)
                  SetPixel(hdc,i,r.bottom-5-nBufScaled[i],RGB(0,0,255));//вывод точек
                 break;
 
             }
 
             case CURVE:
             {
                 MoveToEx(hdc,0,r.bottom-5-nBufScaled[0],NULL);
                 for(int i=1;i<500;i++)
                  LineTo(hdc,i,r.bottom-5-nBufScaled[i]);//вывод отрезков
             }
         }
     }
     SelectPen(hdc,hOldPen);
     EndPaint(hwnd,&ps);
}
 
//функция обработки сообщения WM_DESTROY
void OnDestroy(HWND)
{
    DeleteObject(hPen);
    PostQuitMessage(0);
}
 
//оконная процедура немодального диалога
BOOL CALLBACK DlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
        HANDLE_MSG(hwnd,WM_INITDIALOG,DlgOnInitDialog);
        HANDLE_MSG(hwnd,WM_COMMAND,DlgOnCommand);
 
        default:
         return FALSE;
    }
}
 
//функция обработки сообщения WM_INITDIALOG для диалогового окна
BOOL DlgOnInitDialog(HWND hwnd, HWND,LPARAM)
{
    char S[10];//строка для обмена данными со списком LISTBOX
    SendDlgItemMessage(hwnd,Mode,BM_SETCHECK,1,0L);//Нажать кнопку режима
 
    for(int i=0;i<8;i++)//заполнение списка LISTBOX строками текста
    {
        wsprintf(S,"%d%%",nScales[i]);//пересылка в строку числа и знака %
        SendDlgItemMessage(hwnd,ID_SCALE,LB_ADDSTRING,0,(LPARAM)S);
    }
    SendDlgItemMessage(hwnd,ID_SCALE,LB_SETCURSEL,nScaleIndex,0L);
    return TRUE;
}
 
//функция обработки сообщений WM_COMMAND для диалогового окна
void DlgOnCommand(HWND hwnd,int id,HWND,UINT codeNotify)
{
    switch(id)//код элемента управления
    {
        case IDOK://сообщение от кнопки закрыть
        case IDCANCEL://сообщение от системного меню диалога
         DestroyWindow(hwnd);//уничтожение окна немодального диалога
         hSettingsBox=NULL;//сбросим в нуль его дескриптор
         break;
 
        case ID_DOTS://сообщение от кнопки "Точки"
         Mode=DOTS;//устновим режим "Точки"
         InvalidateRect(GetParent(hwnd),NULL,TRUE);//инициируем WM_PAINT
         break;
 
        case ID_CURVE://сообщение от кнопки "Огибащая"
         Mode=CURVE;//установим режим "Огибающая"
         InvalidateRect(GetParent(hwnd),NULL,TRUE);//инициируем WM_PAINT
         break;
 
        case ID_SCALE://сообщение от списка, проанализируем извещение
         if(codeNotify==LBN_SELCHANGE)//если изменилось выделение в списке
         {
             nScaleIndex=(int)SendDlgItemMessage(hwnd,ID_SCALE,LB_GETCURSEL,0,0);
             nCurrentScales=(float)nScales[nScaleIndex]/100;//Преобразование строки в число
 
             for(int i=0;i<500;i++)//масштабирование спектра в соответствии
              nBufScaled[i]=nBuf[i]*nCurrentScales;//с новым масштабом
 
            InvalidateRect(GetParent(hwnd),NULL,TRUE);//инициируем WM_PAINT
         }
    }
}

Собственно в нём ошибка если есть то разве что в последней функции DlgOnCommand в case ID_SCALE (строка 197), так как именно там обрабатываются сообщения от моего LISTBOX с диалогового окна, все остальные функции работают корректно. Ну ещё возможно что есть ошибка при заполнении LISTBOX (это функция DlgOnInitDialog (строка 162)), хотя вроде заполнился он нормально и все 8 строк в нём присутствуют.

Сама программа,если интересно, выводит график, который она читает из dat файла (считывает первые 1000 байт). Файл dat с нормальным графиком могу предоставить, хотя можно тупо открыть любой файл чтобы программа считала с него 1000 байт, график только рандомный получится.

На скриншоте видно что ни один пункт в LISTBOX "Масштаб" не выбран и мышкой не выбирается.
0
Изображения
 
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.11.2011, 11:40
Здравствуйте! Я подобрал для вас темы с ответами на вопрос "Поймать" сообщение от LISTBOX (C++):

В зависимости от времени года "весна", "лето", "осень", "зима" определить погоду "тепло", "жарко", "холодно", "очень холодно" - C++
В зависимости от времени года &quot;весна&quot;, &quot;лето&quot;, &quot;осень&quot;, &quot;зима&quot; определить погоду &quot;тепло&quot;, &quot;жарко&quot;, &quot;холодно&quot;, &quot;очень холодно&quot;. Я так...

Задача "Максимальный подпалиндром" не могу поймать ошибку. - C++
Палиндромом называется строка, которая одинаково читается как слева направо, так и справа налево. Подпалиндромом данной строки называется...

Задача: игра "Поймать парасёнка" - C++
Описание &quot;Поймать парасёнка&quot; - один из видов игры в карты. Допустим за игральным столом 4 игрока. Ваша задача посчитать итоговый...

Реализовать классы "Воин", "Пехотинец", "Винтовка", "Матрос", "Кортик" (наследование) - C++
Разработать программу с использованием наследования классов, реализующую классы: − воин; − пехотинец(винтовка); − матрос(кортик). ...

Создать класс "Книга" с полями "название книги", "количество страниц", "год издания" - C++
Создать класс Книга поля: название книги,количество страниц,год издания методы: вычислить сколько лет книге и количество дней прошедших...

Создать класс "Вентилятор" содержащий в себе классы: "Двигатель", "Контроллер", "Пульт управления" - C++
Помогите с кодом написания задачи, не понимаю как написать классы в классе. Нужно создать класс &quot;вентилятор&quot; содержащий в себе классы:...

42
Gepar
1177 / 533 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
09.11.2011, 20:36  [ТС] #31
programina, так оно всё равно ничего не выбирается и не изменяется (хотя ветка вызывается при этом регулярно, это я сужу по тому что я туда MessageBox добавил так вот он то вызывался часто)

Добавлено через 3 минуты
Точнее не совсем ничего не выбирается - если поклацать по листу то можно выбрать 200 (график изменится), при этом 200 выделяться не будут и больше ничего выбрать после этого будет нельзя (график меняться больше не будет).
0
programina
1914 / 599 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
09.11.2011, 20:37 #32
как не изменяется скажешь масштаб не меняется когда закрываешь диалог с процентами
или тебе надо чтобы график менялся динамично щелкая по строкам в листбоксе?
0
Gepar
1177 / 533 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
09.11.2011, 20:40  [ТС] #33
Убрал WM_NOTIFY из ресурсов - теперь строчка выделяется (а я то думал именно оно нужно чтобы сообщения присылались, хех), но теперь я могу выбрать либо 100 либо 200 (притом можно выбрать 125 либо ещё чего, всё равно, при клике по листу установится значение 200 (и график перерисуется соответственно) ). Те: изначально при открытии выбрано 100 по умолчанию, а я могу выбрать 200 и всё. Дальше что не выбирай - ничего не меняется и при закрытии и открытии диалогового окна установлено 200.
0
programina
1914 / 599 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
09.11.2011, 20:42 #34
давай я скину тебе твой переделанный проект
у меня все масштабы выбираются
0
Gepar
1177 / 533 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
09.11.2011, 20:43  [ТС] #35
Вот, честно, уж не думал что столько проблем будет с нещасным листбоксом, в этом WINAPI я смотрю так заблудиться можно.

Добавлено через 25 секунд
programina, давай, я посмотрю и сравню
0
programina
1914 / 599 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
09.11.2011, 20:45 #36
Лови
1
Вложения
Тип файла: zip WinProjInCodeBlocks.zip (12.5 Кб, 11 просмотров)
Gepar
1177 / 533 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
09.11.2011, 20:51  [ТС] #37
programina, сейчас посмотрю, опытным методом определил почему всегда 200
C++
1
nScaleIndex=(int)SendDlgItemMessage(GetParent(hwnd),ID_SCALE,LB_GETCURSEL,0,0);
при клике по листу у меня возвращает 0, а нулевой элемент в массиве у меня 200, только почему же оно 0 то всё время у меня возвращает...

Добавлено через 1 минуту
programina, да, Ваш вариант работает как положено, сейчас попробую найти какая строка у Вас отличается от моих наработок.
0
programina
1914 / 599 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
09.11.2011, 20:52 #38
Ну ты скажи у тебя все масштабы выбираются? А то вдруг дело не в коде

PS: не отвечай
стормозила чуточку
0
Gepar
1177 / 533 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
09.11.2011, 20:59  [ТС] #39
Хм, едиснтвенное отличие что я нашёл это вызов OnPaint в конце, правда он и так должен вызываться же после InvalidateRect да и не должен влиять на сам график.
1
programina
1914 / 599 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
09.11.2011, 21:07 #40
Gepar удали онпайнт я забыла убрать

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
        case ID_SCALE:///сообщение от списка, проанализируем извещение
         //if(codeNotify==LBN_SELCHANGE)//если изменилось выделение в списке
         //{
             nScaleIndex=(int)SendDlgItemMessage(hwnd,ID_SCALE,LB_GETCURSEL,0,0);
             nCurrentScales=(float)nScales[nScaleIndex]/100;//Преобразование строки в число
 
             for(int i=0;i<500;i++)//масштабирование спектра в соответствии
              nBufScaled[i]=nBuf[i]*nCurrentScales;//с новым масштабом
 
            InvalidateRect(GetParent(hwnd),NULL,TRUE);//инициируем WM_PAINT
 
            break;
         //}
0
Gepar
1177 / 533 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
09.11.2011, 22:18  [ТС] #41
Я так и не смог найти тогда отличия в коде, сейчас вот открыл в двух окна оба кода и ищу отличие, ато так не интересно когда работать то работает, но непонятно почему начало работать

Добавлено через 13 минут
Нашёл я уже в чём проблема, я когда редактировал немного не тому окну запросы SendDlgItemMessage отправлял (я отправлял родительскому окну, те самому графику, а не диалоговому окну).

Добавлено через 3 минуты
Хотя если кто знает какое сообщение и через какой параметр мы получаем елс есть изменения в списке то не молчите, автор книги хотел их ловить через
C++
1
if(codeNotify==LBN_SELCHANGE)
но на практике это что-то не сработало.
0
programina
1914 / 599 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
10.11.2011, 10:44 #42
У меня MinGW иногда ругается если ставить if в case
Как с этим у других компиляторов не знаю..

Добавлено через 2 часа 24 минуты
Из какой книги твой пример?
0
Gepar
1177 / 533 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
10.11.2011, 10:49  [ТС] #43
Цитата Сообщение от programina Посмотреть сообщение
Из какой книги твой пример?
Из книги Финогенова.

Цитата Сообщение от programina Посмотреть сообщение
У меня MinGW иногда ругается если ставить if в case
У меня то не ругался, но дело в том что та ветка никогда не выполнялась ведь, а по задумке автора она должна была вызываться при каких-либо изменениях в листе.
0
10.11.2011, 10:49
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
10.11.2011, 10:49
Привет! Вот еще темы с ответами:

Создать абстрактный класс "Издание" и производные классы "Книга", "Статья", "Электронный ресурс" - C++
1. Создать абстрактный класс Издание с методами, позволяющими вывести на экран информацию об издании, а также определить является ли данное...

Определить тип данных "Запись", имеющий поля "Фамилия", "Пол", "Зарплата" - C++
определить тип данных запись имеющий поля фамилия пол зарплата. определить массив из 10 записей. в программе ввести в массив данные и...

Создать иерархию классов "Фирма", "Бухгалтер", "Сотрудник", "Зарплата" - C++
Само по себе понятие &quot;зарплата&quot; не особенно конкретное: оно включает и почасовую, и ставочную зарплату, и комиссионные, и процент с продаж....

по строкам.замените в слове сочетание "му" на "а" , а букву "ы" на "ца". очень нужно - C++
замените в слове сочетание &quot;му&quot; на &quot;а&quot; , а букву &quot;ы&quot; на &quot;ца&quot;. очень нужно Добавлено через 21 час 4 минуты неужели никто не знает...


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

Или воспользуйтесь поиском по форуму:
43
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru