Форум программистов, компьютерный форум, киберфорум
Наши страницы
C++: WinAPI
Войти
Регистрация
Восстановить пароль
 
ponchic
-4 / 2 / 1
Регистрация: 21.03.2015
Сообщений: 133
1

Как сделать чтобы перерисовывалось то же что и было?

20.12.2015, 20:40. Просмотров 261. Ответов 1
Метки нет (Все метки)

Помогите одарённому человеку, я ещё совсем новичок в винапи, поэтому не надо писать "ТАм в паинте делаешь снимок и потом его перерисовываешь витблт ом";
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
//////////////////////////////////////////////////////////////////////
// Scribble.cpp
#include <windows.h>
#include "KWnd.h"
 
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    MSG msg;
    KWnd mainWnd("Scribble", hInstance, nCmdShow, WndProc); 
 
    while (GetMessage(&msg, NULL, 0, 0))  {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
 
//====================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    static HDC hDC;
    static int x, y;  // позиция курсора мыши
    static BOOL bTracking = FALSE; 
    HDC hdcMem;
    HBITMAP hbmMem;
    HANDLE hOld;
    RECT rect;
    PAINTSTRUCT ps;
 
    switch (uMsg)
    {
    case WM_PAINT:
 
        
        break;
    case WM_CREATE:
        hDC = GetDC(hWnd);
        break;
 
    case WM_LBUTTONDOWN: 
        bTracking = TRUE;
        // начальная позиция
        x = LOWORD(lParam);
        y = HIWORD(lParam);
        MoveToEx(hDC, x, y, NULL);
        break; 
 
    case WM_LBUTTONUP:
        if (bTracking)
            bTracking = FALSE; 
        break; 
 
    case WM_MOUSEMOVE: 
 
        if (bTracking) {
 
            
 
            HPEN hPen1; 
            
            hPen1 = CreatePen(PS_DOT, 5, RGB(0,128,256));
            SelectObject(hDC, hPen1);
 
            // новая позиция
            x = LOWORD(lParam);
            y = HIWORD(lParam);
            LineTo(hDC, x, y);
            
        } 
        break;
 
    case WM_DESTROY:    
        ReleaseDC(hWnd, hDC); 
        PostQuitMessage(0);
        break;
 
        case WM_RBUTTONUP:
        /*RECT rect;
        SetBkColor(hDC, RGB(0,0,0));
        ExtTextOut(hDC, 0, 0, ETO_OPAQUE, rect, NULL, 0, NULL);
        GetClientRect (hWnd, &rect);
        FillRect (hDC, &rect, (HBRUSH)(COLOR_WINDOW+1));
        */
        RECT rect; 
        GetClientRect(hWnd, &rect);
        InvalidateRect(hWnd, &rect, true);
        break;
 
 
    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    return 0;
}
//////////////////////////////////////////////////////////////////////
Вопрос очень простой, видел что нужно делать снимок и потом его выводить (Типа больше никак)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.12.2015, 20:40
Ответы с готовыми решениями:

Как сделать, чтобы можно было взять тригонометрическую функцию из файла или textBox и вставить в код ?
Есть у меня программа(реализация БПФ), но тригонометрическая функция, которая...

Как сделать так, что бы после начала игры, активным было OpenGL-окно, а не консольное?
Всем привет, у Меня тут такая проблемка, даже не знаю как искать ее решение в...

Что нужно сделать чтобы приходило сообщение WM_MOUSEWHEEL?
Сабж в теме..

Как скрыть курсор мыши и захватить мышку, чтобы не было стрелки мыши и получать команды?
Искал статью в инете и команды: Как сделать захват мыши, чтобы сделать...

как сделать , чтобы программа запоминала что было раньше
Я делаю домино на QBasic и там я сделал перемещение фишки по &quot;столу&quot; таким...

1
Operok
178 / 176 / 66
Регистрация: 15.02.2015
Сообщений: 509
Завершенные тесты: 2
21.12.2015, 12:40 2
В общем, дело вот как обстоит.
Получить контекст устройства для рисования можно двумя основными способами:
- BeginPaint(HWND, PAINTSTRUCT*) в обработке сообщения WM_PAINT (не забыть вызвать EndPaint);
- и GetDC(HWND), вызывается когда угодно и рисовать можно когда угодно.
Первый способ нужен для отрисовки недействительной области окна (регион который необходимо перерисовать). Второй используется для рисования в окне "когда нам это надо", но в этом случае нельзя забывать про WM_PAINT, так как при первом же перекрытии окна или его "ресайзе" все наши труды пропадут.
Т.е. нам надо, что бы в WM_PAINT производилось всё то рисование, что мы делали до этого, надо это как-то и где-то "запоминать". По мне, так есть два основных способа: первый, менее ресурсоёмкий, но медленный, это векторный способ - запоминаем все действия (вызываемые GDI функции) и повторяем их в WM_PAINT, можно с помощью метафайлов, можно самому что-нибудь придумать, в любом случае для вашей ситуации это не подходит; второй - это хранить все свои труды в растровом буфере (в простонародье BITMAP), это ещё называют "Двойная буферизация".
Суть двойной буферизации в следующем: все рисование выполняется в буфере (связка совместимого контекста устройства и совместимого битмапа), который лучше всего подготовить заранее и следить за актуальностью его параметров (например размер битмапа), в обработчике WM_PAINT нужно будет просто перенести изображение в контекст устройства нашего окна (та самая BitBlt). Теперь нам не составит труда рисовать линии указателем мыши, нужно просто нарисовать линию в буфере и вызвать функцию InvalidateRect для переноса измененного буфера на экран.

Добавлено через 1 час 21 минуту
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
#include <Windows.h>
 
LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK ChildWndProc(HWND, UINT, WPARAM, LPARAM);
 
ATOM RegClass(HINSTANCE, WNDPROC, LPCWSTR);
 
void OnPaint(HWND, LPPAINTSTRUCT);
void OnSize(HWND, LPSIZE);
void UpdateBuffer(HWND, LPSIZE);
 
LPCWSTR className = L"Main Window";
LPCWSTR windowText = L"Главное окно";
 
HDC memDC = NULL;
HBITMAP memBM = NULL;
SIZE memSize = { 0, 0 };
 
INT WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, INT nCmdShow)
{
    if (!RegClass(hInst, MainWndProc, className)) {
        MessageBoxW(NULL, L"Register main window class Fail!", L"Error", MB_OK | MB_ICONERROR);
        return 1;
    }
    HWND hWnd = CreateWindowW(
        className, 
        windowText,
        WS_OVERLAPPEDWINDOW, 
        CW_USEDEFAULT, 0, 
        CW_USEDEFAULT, 0, 
        NULL, 
        NULL, 
        hInst, 
        NULL);
    if (!hWnd) {
        MessageBoxW(NULL, L"Create main wndow Fail!", L"Error", MB_OK | MB_ICONERROR);
        return 2;
    }
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);
 
    MSG msg;
 
    while (GetMessageW(&msg, NULL, 0, 0)) {
            TranslateMessage(&msg);
            DispatchMessageW(&msg);
    }
    return 0;
}
 
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
    SIZE size;
    static BOOL bTracking = FALSE;
    switch (msg) {
    case WM_CREATE:
        RECT rect;
        GetClientRect(hWnd, &rect);
        UpdateBuffer(hWnd, (LPSIZE)&rect.right);
        break;
    case WM_PAINT:
        BeginPaint(hWnd, &ps);
        OnPaint(hWnd, &ps);
        EndPaint(hWnd, &ps);
        break;
    case WM_ERASEBKGND:
        return 1;
    case WM_SIZE:
        SIZE size;
        size.cx = LOWORD(lParam);
        size.cy = HIWORD(lParam);
        OnSize(hWnd, &size);
        break;
    case WM_LBUTTONDOWN:
        bTracking = TRUE;
        size.cx = LOWORD(lParam);
        size.cy = HIWORD(lParam);
        MoveToEx(memDC, size.cx, size.cy, NULL);
        break;
    case WM_LBUTTONUP:
        bTracking = FALSE;
        break;
    case WM_MOUSEMOVE:
        if (bTracking) {
            HPEN pen = CreatePen(PS_SOLID, 5, RGB(0, 128, 256));
            HGDIOBJ old = SelectObject(memDC, pen);
            size.cx = LOWORD(lParam);
            size.cy = HIWORD(lParam);
            LineTo(memDC, size.cx, size.cy);
            InvalidateRect(hWnd, NULL, FALSE);
        }
        break;
    case WM_DESTROY:
        if (memDC && memBM) {
            memBM = (HBITMAP)SelectObject(memDC, memBM);
            DeleteObject(memBM);
            DeleteDC(memDC);
        }
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProcW(hWnd, msg, wParam, lParam);
    }
    return 0;
}
 
ATOM RegClass(HINSTANCE hInst, WNDPROC proc, LPCWSTR className)
{
    WNDCLASS wc = { 0 };
    wc.hInstance = hInst;
    wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
    wc.lpszClassName = className;
    wc.lpfnWndProc = proc;
    wc.style = CS_HREDRAW | CS_VREDRAW;
 
    return RegisterClassW(&wc);
}
 
void OnPaint(HWND hWnd, LPPAINTSTRUCT lpps)
{
    if (!memDC)
        UpdateBuffer(hWnd, (LPSIZE)&lpps->rcPaint.right);
    BitBlt(lpps->hdc,
        lpps->rcPaint.left,
        lpps->rcPaint.top,
        lpps->rcPaint.right - lpps->rcPaint.left,
        lpps->rcPaint.bottom - lpps->rcPaint.top,
        memDC,
        lpps->rcPaint.left,
        lpps->rcPaint.top,
        SRCCOPY);
}
void OnSize(HWND hWnd, LPSIZE lpSize)
{
 
    if (memSize.cx < lpSize->cx || memSize.cy < lpSize->cy) {
        SIZE newSize = {
            max(memSize.cx, lpSize->cx),
            max(memSize.cy, lpSize->cy)
        };
        UpdateBuffer(hWnd, &newSize);
    }
}
void UpdateBuffer(HWND hWnd, LPSIZE lpSize)
{
    BITMAP bitmap;
    HDC hdc = GetDC(hWnd);
    HDC newDC = CreateCompatibleDC(hdc);
    HBITMAP newBM = CreateCompatibleBitmap(hdc, lpSize->cx, lpSize->cy);
    ReleaseDC(hWnd, hdc);
    newBM = (HBITMAP)SelectObject(newDC, newBM);
    RECT rect = {
        0, 0,
        lpSize->cx,
        lpSize->cy
    };
    FillRect(newDC, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
    if (memBM && memDC) {
        BitBlt(newDC, 0, 0, memSize.cx, memSize.cy, memDC, 0, 0, SRCCOPY);
        memBM = (HBITMAP)SelectObject(memDC, memBM);
        DeleteObject(memBM);
        DeleteDC(memDC);
    }
    memDC = newDC;
    memBM = newBM;
    memSize = *lpSize;
}
Добавлено через 29 минут
Вот с комментариями:
Кликните здесь для просмотра всего текста
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
#include <Windows.h>
 
LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK ChildWndProc(HWND, UINT, WPARAM, LPARAM);
 
ATOM RegClass(HINSTANCE, WNDPROC, LPCWSTR);
 
void OnPaint(HWND, LPPAINTSTRUCT);  //обработчик WM_PAINT
void OnSize(HWND, LPSIZE);               //обработчик WM_SIZE
void UpdateBuffer(HWND, LPSIZE);       //обновление буфера с новыми размерами
 
LPCWSTR className = L"Main Window";
LPCWSTR windowText = L"Главное окно";
 
HDC memDC = NULL;          //совместимый контекст устройства для буфера
HBITMAP memBM = NULL;   //совместимый битмап (по сути сам буфер)
SIZE memSize = { 0, 0 };    //размеры буфера (чтобы лишний раз не спрашивать об этом у memDC или memBM)
 
INT WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, INT nCmdShow)
{
    if (!RegClass(hInst, MainWndProc, className)) {
        MessageBoxW(NULL, L"Register main window class Fail!", L"Error", MB_OK | MB_ICONERROR);
        return 1;
    }
    HWND hWnd = CreateWindowW(
        className, 
        windowText,
        WS_OVERLAPPEDWINDOW, 
        CW_USEDEFAULT, 0, 
        CW_USEDEFAULT, 0, 
        NULL, 
        NULL, 
        hInst, 
        NULL);
    if (!hWnd) {
        MessageBoxW(NULL, L"Create main wndow Fail!", L"Error", MB_OK | MB_ICONERROR);
        return 2;
    }
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);
 
    MSG msg;
 
    while (GetMessageW(&msg, NULL, 0, 0)) {
            TranslateMessage(&msg);
            DispatchMessageW(&msg);
    }
    return 0;
}
 
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
    SIZE size;
    static BOOL bTracking = FALSE;
    switch (msg) {
    case WM_CREATE:
        RECT rect;
        GetClientRect(hWnd, &rect);
                //обновляем буфер (так как старого нет, то будет просто создан новый)
        UpdateBuffer(hWnd, (LPSIZE)&rect.right);
        break;
    case WM_PAINT:
        BeginPaint(hWnd, &ps);
        OnPaint(hWnd, &ps);
        EndPaint(hWnd, &ps);
        break;
    case WM_ERASEBKGND:
                //для того чтобы система не закрашивала нам рабочую область
        return 1;
    case WM_SIZE:
        SIZE size;
        size.cx = LOWORD(lParam);
        size.cy = HIWORD(lParam);
        OnSize(hWnd, &size);
        break;
    case WM_LBUTTONDOWN:
        bTracking = TRUE;
        size.cx = LOWORD(lParam);
        size.cy = HIWORD(lParam);
        MoveToEx(memDC, size.cx, size.cy, NULL);
        break;
    case WM_LBUTTONUP:
        bTracking = FALSE;
        break;
    case WM_MOUSEMOVE:
        if (bTracking) {
            HPEN pen = CreatePen(PS_SOLID, 5, RGB(0, 128, 256));
            HGDIOBJ old = SelectObject(memDC, pen);
            size.cx = LOWORD(lParam);
            size.cy = HIWORD(lParam);
            LineTo(memDC, size.cx, size.cy);
                        //делаем рабочую область нашего окна недействительной для переноса наших трудов на экран
            InvalidateRect(hWnd, NULL, FALSE);
        }
        break;
    case WM_DESTROY:
        if (memDC && memBM) { //удаляем буфер
            memBM = (HBITMAP)SelectObject(memDC, memBM);
            DeleteObject(memBM);
            DeleteDC(memDC);
        }
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProcW(hWnd, msg, wParam, lParam);
    }
    return 0;
}
 
ATOM RegClass(HINSTANCE hInst, WNDPROC proc, LPCWSTR className)
{
    WNDCLASS wc = { 0 };
    wc.hInstance = hInst;
    wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
    wc.lpszClassName = className;
    wc.lpfnWndProc = proc;
    wc.style = CS_HREDRAW | CS_VREDRAW;
 
    return RegisterClassW(&wc);
}
 
void OnPaint(HWND hWnd, LPPAINTSTRUCT lpps)
{
    if (!memDC)
                //если буфер всё ещё не создан, то надо создать (на всякий)
        UpdateBuffer(hWnd, (LPSIZE)&lpps->rcPaint.right);
        //собственно сам "БитБлт" (переносим изображение из буфера на экран)
    BitBlt(lpps->hdc,
        lpps->rcPaint.left,
        lpps->rcPaint.top,
        lpps->rcPaint.right - lpps->rcPaint.left,
        lpps->rcPaint.bottom - lpps->rcPaint.top,
        memDC,
        lpps->rcPaint.left,
        lpps->rcPaint.top,
        SRCCOPY);
}
void OnSize(HWND hWnd, LPSIZE lpSize)
{
        //обновляем буфер только если его нужно увеличить (чтобы сохранялось нарисованное)
    if (memSize.cx < lpSize->cx || memSize.cy < lpSize->cy) {
        SIZE newSize = {
            max(memSize.cx, lpSize->cx),
            max(memSize.cy, lpSize->cy)
        };
        UpdateBuffer(hWnd, &newSize);
    }
}
void UpdateBuffer(HWND hWnd, LPSIZE lpSize)
{
    HDC hdc = GetDC(hWnd);
        //создаём совместимый контекст (совместимый с контекстом экрана)
    HDC newDC = CreateCompatibleDC(hdc);   
        //и совместимый битмап
    HBITMAP newBM = CreateCompatibleBitmap(hdc, lpSize->cx, lpSize->cy);   
    ReleaseDC(hWnd, hdc);
        //обязательно выбираем битмап в контекст (по правилам хорошего тона, после работы с контекстом перед его удалением/освобождением, нужно выбрать в него "старые" GDI объекты, поэтому я сохраняю старый битмап)
    newBM = (HBITMAP)SelectObject(newDC, newBM);
    RECT rect = {
        0, 0,
        lpSize->cx,
        lpSize->cy
    };
        //рисуем на белом фоне
    FillRect(newDC, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
    if (memBM && memDC) {
                //если есть старый буфер, то копируем его содержимое в новый
        BitBlt(newDC, 0, 0, memSize.cx, memSize.cy, memDC, 0, 0, SRCCOPY);
                //а старый удаляем
        memBM = (HBITMAP)SelectObject(memDC, memBM);
        DeleteObject(memBM);
        DeleteDC(memDC);
    }
        //буер обновлён
    memDC = newDC;
    memBM = newBM;
    memSize = *lpSize;
}
2
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
21.12.2015, 12:40

Как сделать так чтобы было видно что подставляться в уравнения
Я хочу чтобы через равно програма подставляла числа, а через следующие...

Как сделать так, чтобы маткад не учитывал всё, что было написано раньше в документе?
У меня есть маткадовский документ. Я хочу продолжить в нём писать дальше, но...

Как сделать чтобы не выполнялось, при нажатии на Space, то что было вызвано ранее кликом мышки
Всем доброго времени суток. В C# я новичок. Сделал простой видео проигрыватель,...


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

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

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