С Новым годом! Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.61/18: Рейтинг темы: голосов - 18, средняя оценка - 4.61
0 / 0 / 0
Регистрация: 23.08.2009
Сообщений: 3

Поворот DC

23.08.2009, 18:08. Показов 3834. Ответов 4
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте! Сегодня начал изучать gdi и решил написать простенькую игрушку. Какое-то изображение (танк, к примеру) ездит по фону по нажатию стрелок на клавиатуре. Сделал успешно, всё работает. Но тут пришла мысль поворачивать этот танк. Выбрал для этой цели функцию SetWorldTransform. Заполнил поля структуры, как описано в MSDN. Но не работает. После применения вышеупомянутой функции содержимое DC пропадает. Помогите, пожалуйста, найти ошибку Исходник прилагаю. Компилятор VS2008, в ресурсах - IDB_BITMAP1 (битмап с танком) и IDB_BITMAP2 (фоновое изображение).

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
#include "resource1.h"
#include <windows.h>
#include <math.h>
 
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
void RegisterClass(TCHAR*, HINSTANCE);
 
int x=0,y=0;
double PI = 3.14159265358;
float radians=1;
float cosine;
float sine;
 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hProvInstance, PSTR szCmdLine, int iCmdShow)
{
    TCHAR szAppName[] = L"Hello Win";
    HWND hwnd;
    MSG msg;
    RegisterClass(szAppName, hInstance);
    hwnd = CreateWindow( szAppName, L"my window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL );
    ShowWindow( hwnd, iCmdShow );
    UpdateWindow( hwnd );
 
    while( GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    }
    return (int)msg.wParam;
}
 
void RegisterClass(TCHAR * name, HINSTANCE hInst)
{
    WNDCLASSEX wc;
    wc.cbSize = sizeof(wc);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInst;
    wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
    wc.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
    wc.hCursor = LoadCursor( NULL, IDC_ARROW );
    wc.hbrBackground = NULL;
    wc.lpszClassName = name;
    wc.lpszMenuName = NULL;
    RegisterClassEx( &wc );
 
}
LRESULT CALLBACK WndProc( HWND hwnd,UINT iMsg,WPARAM wParam,LPARAM lParam )
{
    static RECT r;  
    static HBITMAP bground;
    static HDC MemDC;
    static HDC MemDC1;
    static HBRUSH hbr;
    static HBITMAP tank;
    PAINTSTRUCT ps;
    HDC hdc;    
 
    switch(iMsg){
        case WM_CREATE:
            cosine = (float)cos(radians);
            sine = (float)sin(radians);
            hdc=GetDC(hwnd);
            GetClientRect(hwnd,&r);
 
            MemDC=CreateCompatibleDC(hdc);
            SetGraphicsMode(MemDC,GM_ADVANCED);
 
            MemDC1=CreateCompatibleDC(MemDC);
            tank=LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE (IDB_BITMAP1));
            SetGraphicsMode(MemDC1,GM_ADVANCED);
            SelectObject(MemDC1,tank);
 
            GetClientRect(hwnd,&r);
            bground=CreateCompatibleBitmap(hdc,r.right-r.left,r.bottom-r.top);
            SelectObject(MemDC,bground);
 
            hbr=CreatePatternBrush(LoadBitmap(GetModuleHandle(NULL),MAKEINTRESOURCE(IDB_BITMAP2)));
            ReleaseDC(hwnd,hdc);
            return 0;
 
        case WM_PAINT:
            hdc = BeginPaint(hwnd, &ps);
            FillRect(MemDC,&r,hbr);
            BitBlt(MemDC,x,y,GetDeviceCaps(MemDC1,HORZRES),GetDeviceCaps(MemDC1,VERTRES),MemDC1,0,0,SRCCOPY);   
            BitBlt(hdc,0,0,r.right-r.left,r.bottom-r.top,MemDC,0,0,SRCCOPY);
            EndPaint(hwnd, &ps);
            return 0;
 
        case WM_DESTROY:
            PostQuitMessage(0);
 
        case WM_KEYDOWN:
            switch(wParam){
                case VK_UP:
                    y-=10;
                    InvalidateRect(hwnd,NULL,TRUE);
                    break;
                case VK_DOWN:
                    y+=10;
                    InvalidateRect(hwnd,NULL,TRUE);
                    break;
                case VK_LEFT:
                    XFORM xForm;
                    xForm.eM11 = cosine; 
                    xForm.eM12 = sine;
                    xForm.eM21 = -sine; 
                    xForm.eM22 = cosine;
                    xForm.eDx  = (FLOAT) 0; 
                    xForm.eDy  = (FLOAT) 0; 
                    SetWorldTransform(MemDC1,&xForm);
                    x-=10;
                    InvalidateRect(hwnd,NULL,TRUE);
                    break;
                case VK_RIGHT:
                    x+=10;
                    InvalidateRect(hwnd,NULL,TRUE);
            }
            return 0;
 
    }
    return DefWindowProc( hwnd, iMsg, wParam, lParam );
}
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
23.08.2009, 18:08
Ответы с готовыми решениями:

Не могу сделать поворот матрицы на каждое нажатие, и её нормальный поворот
var Form1: TForm1; m, n: integer; i, j: byte; b, a: array of integer; implementation uses Unit2, Unit3;

Поворот
Собсно есть треуголник в реальных координатах(отмасштабирован).Требуется повернуть его на N градусов(например 10:) ).Подскажите...

Поворот
Помогите пожалуйста, мне нужно повернуть фигуру, только я не знаю как это сделать если использовать glRotate(45, 0,0, 1) то фигуру...

4
 Аватар для Otaka
1857 / 714 / 55
Регистрация: 11.12.2008
Сообщений: 1,019
23.08.2009, 18:34
Скажи, что ты подразумеваешь под этим?
C++
1
2
3
4
 xForm.eM11 = cosine; 
 xForm.eM12 = sine;
 xForm.eM21 = -sine; 
 xForm.eM22 = cosine;
Там нужно cos(угол на который нужно тебе повернуть изображение) sin(angle).

Добавлено через 2 минуты
Не забудь, что нужно будет еще использовать SetViewportOrgExt для смещения базовой точки вывода, иначе картинка у тебя будет ездить по кругу.
А вообще, эта тема столько раз поднималась на форуме. Юзай поиск.
0
0 / 0 / 0
Регистрация: 23.08.2009
Сообщений: 3
23.08.2009, 19:59  [ТС]
Цитата Сообщение от Otaka Посмотреть сообщение
Скажи, что ты подразумеваешь под этим?
C++
1
2
cosine = (float)cos(radians);
sine = (float)sin(radians);
Если взять код отсюда: Повернуть Image , то результат такой же - изображение прячется неизвестно куда.
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
#include "resource1.h"
#include <windows.h>
#include <math.h>
 
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
void RegisterClass(TCHAR*, HINSTANCE);
void RotateDC(HDC dc,float angle);
 
int x=0,y=0;
double PI = 3.14159265358;
 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hProvInstance, PSTR szCmdLine, int iCmdShow)
{
    TCHAR szAppName[] = L"Hello Win";
    HWND hwnd;
    MSG msg;
    RegisterClass(szAppName, hInstance);
    hwnd = CreateWindow( szAppName, L"my window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL );
    ShowWindow( hwnd, iCmdShow );
    UpdateWindow( hwnd );
 
    while( GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    }
    return (int)msg.wParam;
}
 
void RegisterClass(TCHAR * name, HINSTANCE hInst)
{
    WNDCLASSEX wc;
    wc.cbSize = sizeof(wc);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInst;
    wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
    wc.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
    wc.hCursor = LoadCursor( NULL, IDC_ARROW );
    wc.hbrBackground = NULL;
    wc.lpszClassName = name;
    wc.lpszMenuName = NULL;
    RegisterClassEx( &wc );
 
}
LRESULT CALLBACK WndProc( HWND hwnd,UINT iMsg,WPARAM wParam,LPARAM lParam )
{
    static RECT r;  
    static HBITMAP bground;
    static HDC MemDC;
    static HDC MemDC1;
    static HBRUSH hbr;
    static HBITMAP tank;
    PAINTSTRUCT ps;
    HDC hdc;    
 
    switch(iMsg){
        case WM_CREATE:
            hdc=GetDC(hwnd);
            GetClientRect(hwnd,&r);
 
            MemDC=CreateCompatibleDC(hdc);
            SetGraphicsMode(MemDC,GM_ADVANCED);
 
            MemDC1=CreateCompatibleDC(MemDC);
            tank=LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE (IDB_BITMAP1));
            SetGraphicsMode(MemDC1,GM_ADVANCED);
            SelectObject(MemDC1,tank);
 
            GetClientRect(hwnd,&r);
            bground=CreateCompatibleBitmap(hdc,r.right-r.left,r.bottom-r.top);
            SelectObject(MemDC,bground);
 
            hbr=CreatePatternBrush(LoadBitmap(GetModuleHandle(NULL),MAKEINTRESOURCE(IDB_BITMAP2)));
            ReleaseDC(hwnd,hdc);
            return 0;
 
        case WM_PAINT:
            hdc = BeginPaint(hwnd, &ps);
            FillRect(MemDC,&r,hbr);
            BitBlt(MemDC,x,y,GetDeviceCaps(MemDC1,HORZRES),GetDeviceCaps(MemDC1,VERTRES),MemDC1,0,0,SRCCOPY);   
            BitBlt(hdc,0,0,r.right-r.left,r.bottom-r.top,MemDC,0,0,SRCCOPY);
            EndPaint(hwnd, &ps);
            return 0;
 
        case WM_DESTROY:
            PostQuitMessage(0);
 
        case WM_KEYDOWN:
            switch(wParam){
                case VK_UP:
                    y-=10;
                    InvalidateRect(hwnd,NULL,TRUE);
                    break;
                case VK_DOWN:
                    y+=10;
                    InvalidateRect(hwnd,NULL,TRUE);
                    break;
                case VK_LEFT:
                    RotateDC(MemDC1,30);
                    x-=10;
                    InvalidateRect(hwnd,NULL,TRUE);
                    break;
                case VK_RIGHT:
                    x+=10;
                    InvalidateRect(hwnd,NULL,TRUE);
            }
            return 0;
 
    }
    return DefWindowProc( hwnd, iMsg, wParam, lParam );
}
 
void RotateDC(HDC dc,float angle){
    SetViewportOrgEx(dc,x,y,NULL);
    XFORM xform;
     
    angle = angle * 3.1416 / 180.0;
     
    xform.eDx = 0.0f;
    xform.eDy = 0.0f;
    xform.eM11 = cos(angle);
    xform.eM12 = sin(angle);
    xform.eM21 = -sin(angle);
    xform.eM22 = cos(angle);
     
    SetGraphicsMode(dc, GM_ADVANCED);
    SetWorldTransform(dc, &xform);
}
0
 Аватар для Otaka
1857 / 714 / 55
Регистрация: 11.12.2008
Сообщений: 1,019
23.08.2009, 20:17
Твой исходник скомпилить не могу, так как VC у меня не установлен. А вот тот по ссылке перепроверен уже мной во многих приложениях.
А почему у тебя переменная угла всегда одна и та же? Равна 1 тоесть где-то ХХ.ххх градусов?
Таким образом все твое рисование оказывается за экраном. Ничего удивительного.
Фон нужно рисовать без скручивания а на танк нужно еще применить SetViewportOrgExt.
Посмотри по ссылке, которую сам же и нашел, мой пример про жука. Там все написано.
0
0 / 0 / 0
Регистрация: 23.08.2009
Сообщений: 3
24.08.2009, 01:55  [ТС]
Вот такой эксперимент:

C++
1
2
3
4
5
6
7
TransparentBlt(BackgroundDC,x,y,Tank.bmWidth,Tank.bmHeight,TankDC,0,0,Tank.bmWidth,Tank.bmHeight,0xffffff);
//TransparentBlt возвращает true
SetViewportOrgEx(TankDC,1,1,NULL);
//SetViewportOrgEx возвращает nonzero
TransparentBlt(BackgroundDC,x,y,Tank.bmWidth,Tank.bmHeight,TankDC,0,0,Tank.bmWidth,Tank.bmHeight,0xffffff);
//TransparentBlt возвращает false
//Делаем GetLastError, получаем ошибку 87 - "Параметр задан неверно"
С SetWorldTransform всё тоже самое.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
24.08.2009, 01:55
Помогаю со студенческими работами здесь

Поворот
Добрый день! Нужно вращать изображение по оси X. Код вращения: glClear(GL_COLOR_BUFFER_BIT); glPushMatrix(); if (angle...

поворот на 90...
Хочу повернуть матрицу по часовой стрелке на 90 градусов, но че-то не получается... Помогите найти ошибку... Вот мой код: #include...

Поворот
Почему в процедуре DrawTestObj если Scale написать раньше Rotate, то прямоугольник не повернется горизонтально(длинна сторона параллельна...

Поворот тела в 3д
К жесткому телу ориентация которого в пространстве задана тремя точками A,B,C жестко присоединена точка D. Изменили ориентацию тела в...

Поворот изображения
program pr1; uses crt, GraphABC; const n=1000; x0=250; y0=150; pi=3.14; type Arr=array of integer; procedure Show(x,y:Arr; k:real);...


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

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
Учёным и волонтёрам проекта «Einstein@home» удалось обнаружить четыре гамма-лучевых пульсара в джете Млечного Пути
Programma_Boinc 01.01.2026
Учёным и волонтёрам проекта «Einstein@home» удалось обнаружить четыре гамма-лучевых пульсара в джете Млечного Пути Сочетание глобально распределённой вычислительной мощности и инновационных. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru