Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Помогите перерисовка окон встроенных классов


Автор: yngwie19 5.3.2009, 12:55
Всем привет. Я делаю присер из книги Финогенова. "Основы программирования WIN32" и разбираю один пример, ниже выкладываю его код (всего 2 файлика gui.cpp и gui.h):
gui.cpp
Код

#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include "gui.h"

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE,LPSTR,int)
{
    LPSTR lpszClassName = "MainWindow";
    LPSTR lpszTitle = "Программа 8-3";
    MSG msg;
    WNDCLASS wc = {0};
    
    InitCommonControls();
    
    // Описание и регистрация класса MainWindow
    wc.lpszClassName = lpszClassName;
    wc.hInstance = hInstance;
    wc.lpfnWndProc = MainWindowWndProc;
    wc.hCursor = LoadCursor(NULL,IDC_ARROW);
    wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
    wc.hbrBackground = GetStockBrush(LTGRAY_BRUSH);
    
    if(!RegisterClass(&wc))
        MessageBox(NULL,"Класс MainWindow не зарегестрирован","Ошибка",MB_OK | MB_ICONSTOP);

    // Описание и регистрация класса GraphWindow
    wc.lpszClassName = lpszGraphClassName;
    wc.lpfnWndProc = GraphWndProc;
    wc.hbrBackground = GetStockBrush(WHITE_BRUSH);
    
    if(!RegisterClass(&wc))
        MessageBox(NULL,"Класс GraphWindow не зарегестрирован","Ошибка",MB_OK | MB_ICONSTOP);
    
    HWND hwnd = CreateWindow(lpszClassName,lpszTitle,WS_SYSMENU | WS_CAPTION,10,10,500,277,HWND_DESKTOP,NULL,hInstance,NULL);
    ShowWindow(hwnd,SW_SHOWNORMAL);
    
    while(GetMessage(&msg,NULL,0,0))
        DispatchMessage(&msg);
    
    return 0;
}

// Функции класса MainWindow
LRESULT CALLBACK MainWindowWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
        HANDLE_MSG(hwnd,WM_CREATE,MainWindowOnCreate);
        HANDLE_MSG(hwnd,WM_HSCROLL,MainWindowOnHScroll);
        HANDLE_MSG(hwnd,WM_CTLCOLORSTATIC,MainWindowOnCtlColorStatic);
        HANDLE_MSG(hwnd,WM_DESTROY,MainWindowOnDestroy);
        default:
            return DefWindowProc(hwnd,msg,wParam,lParam);
    }
}

BOOL MainWindowOnCreate(HWND hwnd, LPCREATESTRUCT)
{
    // Создание окна для вывода графика
    CreateWindow(lpszGraphClassName,NULL,WS_CHILD | WS_VISIBLE | WS_BORDER,10,10,220,200,hwnd,NULL,(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),NULL);
    
    // Создание окна для вывода текста для TrackBar
    CreateWindow("STATIC","Отношение частот по осям",WS_CHILD | WS_VISIBLE,270,30,180,15,hwnd,NULL,(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),NULL);
    
    // Создание окна TrackBar
    hwndTrack = CreateWindow(TRACKBAR_CLASS,NULL,WS_CHILD | WS_VISIBLE | TBS_AUTOTICKS,250,55,210,30,hwnd,NULL,(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),NULL);
    SendMessage(hwndTrack,TBM_SETRANGE,TRUE,MAKELPARAM(1,10));
    SendMessage(hwndTrack,TBM_SETPAGESIZE,0,1);
    SendMessage(hwndTrack,TBM_SETPOS,TRUE,1);
    
    // Создание окна вывода нумерации под TrackBar
    CreateWindow("STATIC","1   2   3   4   5   6   7   8   9  10",WS_CHILD | WS_VISIBLE,260,85,220,22,hwnd,NULL,(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),NULL);
    
    // Создание окна вывода текста для ScrollBar
    CreateWindow("STATIC","Сдвиг фаз в градусах",WS_CHILD | WS_VISIBLE,280,130,200,22,hwnd,NULL,(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),NULL);
    
    // Создание окна ScrollBar для изменения фазы
    sinfo.cbSize = sizeof(SCROLLINFO);
    sinfo.fMask = SIF_ALL;
    sinfo.nMin = 0;
    sinfo.nMax = 180;
    sinfo.nPage = 18;
    sinfo.nPos = 0;
    
    hwndScroll = CreateWindow("SCROLLBAR",NULL,WS_CHILD | WS_VISIBLE,260,160,200,20,hwnd,NULL,(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),NULL);
    SetScrollInfo(hwnd,SB_CTL,&sinfo,TRUE);
    
    // Создание окна надписи под шкалой Scroll "0" и 180
    CreateWindow("STATIC","0",WS_CHILD | WS_VISIBLE,260,185,10,25,hwnd,NULL,(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),NULL);
    CreateWindow("STATIC","180",WS_CHILD | WS_VISIBLE,445,185,25,25,hwnd,NULL,(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),NULL);
    
    // Создание окна надписи текущего значения ScrollBar
    hwndStatic = CreateWindow("STATIC","00",WS_CHILD | WS_VISIBLE,353,186,30,25,hwnd,NULL,(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),NULL);
    
    return TRUE;
}

void MainWindowOnHScroll(HWND,HWND hwndCtrl, UINT nCodeNotify, int nPos)
{
    char szT[4] = {NULL};
    
    if(hwndCtrl == hwndTrack && nCodeNotify == TB_ENDTRACK)
        nFreq = SendMessage(hwndTrack,TBM_GETPOS,0,0);

    if(hwndCtrl == hwndScroll)
    {
        switch(nCodeNotify)
        {
            case SB_LINERIGHT:
                sinfo.nPos++;
                if(sinfo.nPos > sinfo.nMax)
                    sinfo.nPos = sinfo.nMax;
                SetScrollInfo(hwndScroll,SB_CTL,&sinfo,TRUE);
                break;
            case SB_LINELEFT:
                sinfo.nPos--;
                if(sinfo.nPos < sinfo.nMin)
                    sinfo.nPos = sinfo.nMin;
                SetScrollInfo(hwndScroll,SB_CTL,&sinfo,TRUE);
                break;
            case SB_PAGERIGHT:
                sinfo.nPos+=18;
                if(sinfo.nPos > sinfo.nMax)
                    sinfo.nPos = sinfo.nMax;
                SetScrollInfo(hwndScroll,SB_CTL,&sinfo,TRUE);
                break;
            case SB_PAGELEFT:
                sinfo.nPos-=18;
                if(sinfo.nPos < sinfo.nMin)
                    sinfo.nPos = sinfo.nMin;
                SetScrollInfo(hwndScroll,SB_CTL,&sinfo,TRUE);
                break;
            case SB_THUMBTRACK:
                sinfo.nPos = nPos;
                if(sinfo.nPos < sinfo.nMin)
                    sinfo.nPos = sinfo.nMin;
                if(sinfo.nPos > sinfo.nMax)
                    sinfo.nPos = sinfo.nMax;
                SetScrollInfo(hwndScroll,SB_CTL,&sinfo,TRUE);
                break;    
        }
            wsprintf(szT,"%03d",sinfo.nPos);
            SetWindowText(hwndStatic,szT);
    }
}

HBRUSH MainWindowOnCtlColorStatic(HWND, HDC hdc,HWND hwndCtl, int)
{
    SetBkMode(hdc,TRANSPARENT);
    return GetStockBrush(LTGRAY_BRUSH);
}

void MainWindowOnDestroy(HWND)
{
    PostQuitMessage(0);
}

// Функции класса GraphWindow
LRESULT CALLBACK GraphWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
        HANDLE_MSG(hwnd,WM_PAINT,GraphWindowOnPaint);
        default:
            return DefWindowProc(hwnd,msg,wParam,lParam);
    }
    
}

void GraphWindowOnPaint(HWND hwnd)
{
    
    
}


gui.h
Код

// Глобальные переменные
LPSTR lpszGraphClassName = "GraphWindow";
HWND hwndTrack;
HWND hwndScroll;
HWND hwndStatic;
SCROLLINFO sinfo;
short nFreq = 1;

// Прототипы функций класса MainWindow
LRESULT CALLBACK MainWindowWndProc(HWND,UINT,WPARAM,LPARAM);
BOOL MainWindowOnCreate(HWND,LPCREATESTRUCT);
void MainWindowOnHScroll(HWND,HWND,UINT,int);
HBRUSH MainWindowOnCtlColorStatic(HWND,HDC,HWND,int);
void MainWindowOnDestroy(HWND);

// Прототипы функций класса GraphWindow
LRESULT CALLBACK GraphWndProc(HWND,UINT,WPARAM,LPARAM);
void GraphWindowOnPaint(HWND);



Это программа выводит в белое окно график и с помощью контролов справа может регулировать его. График пока не рисовал но проблемы начались уже до него. Вообщем так несколько вопросов:
1) Почему при запуске программы не прорисовываются для контрола (они же окна со встроенными классами TRACKBAR_CLASS и "SCROLLBAR" соответственно), они появляются только в том случае если перемещать главное окно приложения. Хотя если в   GraphWndProc закоментить макрос HANDLE_MSG(hwnd,WM_PAINT,GraphWindowOnPaint), то все нормально (какое он к ним имеет отношение?). В этом макросе потом будет описан вывод графика в это белое окно.
2) Почему если перемещать каретку на ScrollBar до самого конца вправо, то визуально она доходит только до значения 163, т.е якобы это конец, хотя всего у меня 180 значений.

P.S: Заранее спасибо за Ваши ответы, мне они очень нужны т.к в книге Финогенов этого не описывает.

Автор: GremlinProg 6.3.2009, 19:03
Цитата(yngwie19 @  5.3.2009,  14:55 Найти цитируемый пост)
Почему при запуске программы не прорисовываются для контрола

потому что эти классы используют родительский девайс для рисования, т.е. используют CS_PARENTDC при регистрации
отсюда и зависимость

смотри внимательно на свой код:
Код

...
    switch(msg)
    {
        HANDLE_MSG(hwnd,WM_PAINT,GraphWindowOnPaint);
        default:
            return DefWindowProc(hwnd,msg,wParam,lParam);
    }
...
void GraphWindowOnPaint(HWND hwnd)
{
    
    
}

у тебя тут на WM_PAINT блокируется DefWindowProc, а в обработчике ни каких действий по выводу графики нет,
сделай хотя бы минимум:
Код

void GraphWindowOnPaint(HWND hwnd)
{
    PAINTSTRUCT ps;
    ::BeginPaint(hwnd,&ps);
    ::EndPaint(hwnd,&ps);
}

BeginPaint, на самом деле, много чего делает, в том числе, и уведомляет дочерние компоненты о перерисовке, если они были перекрыты, так что не стоит ее игнорировать, если нечего предложить взамен

Цитата(yngwie19 @  5.3.2009,  14:55 Найти цитируемый пост)
Почему если перемещать каретку на ScrollBar до самого конца вправо, то визуально она доходит только до значения 163, т.е якобы это конец, хотя всего у меня 180 значений.

тут ошибок нет, полоса прокрутки - оконный компонент в том плане, что его окно(ползунок) входит в область расчета, в отличии от трекбаров, поэтому, и параметр sinfo.nPage - не дополнение к sinfo.nMax, а его состаная часть
если хочешь чтобы скроллбар работал как трекбар, то сделай одно из двух:
первое:
Код

    sinfo.nMax = 180;
    sinfo.nPage = 1;

либо второе
Код

    sinfo.nPage = 18;
    sinfo.nMax = 180 + 18;

визуально, решения различаются, смотри сам какое нужно

Автор: yngwie19 6.3.2009, 22:43
GremlinProg, Спасибо тебе огромное ты очень мне помог )))).

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)