Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Работа с графикой 
:(
    Опции темы
Relrin
Дата 5.9.2012, 16:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 20.2.2012

Репутация: нет
Всего: нет



Потиху изучаю WinAPI, и в последствии возникло пару проблем, которые пока не получается решить:
1) у меня есть 7 кнопок, каждая из них отвечает за свои действия. Как обрабатывать ситуации, когда нужны координаты мышки запомнить, причем для эллипса, круга, прямоугольника, и пр, для их рисования это необходимо?
2) как ограничить область рисования, не затрагивая панель, с кнопками?
3) Почему на фрагменте, связанном с рисованием линии, ее как таковую не рисует? Хотя перо создано, цвет задан также?

Код:
Код

#include <windows.h>
#include "stdafx.h"
#include "Lab_1.h"
#include "FormElements.h"
#define MAX_LOADSTRING 100

const int cnt = 7;                                // количество кнопок в программе
FormElements Button[cnt];                        // класс, связанный с кнопками и их событиями

HINSTANCE hInst;                                // текущий экземпляр
TCHAR szTitle[MAX_LOADSTRING];                    // текст строки заголовка
TCHAR szWindowClass[MAX_LOADSTRING];            // имя класса главного окна

// Отправить объявления функций, включенных в этот модуль кода:
ATOM             MyRegisterClass(HINSTANCE hInstance);
BOOL             InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
BOOL DrawLine(HDC hdc, int x1, int y1, int x2, int y2);

// А-ля void main()
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    MSG msg;
    HACCEL hAccelTable;

    // инициализация глобальных строк
    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadString(hInstance, IDC_LAB_1, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // выполнить инициализацию приложения:
    if (!InitInstance (hInstance, nCmdShow)) {return FALSE;}

    hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_LAB_1));

    // цикл сообщений приложения
    while(GetMessage(&msg, NULL, 0, 0))
    {
        //если GetMessage вернул ошибку --> выход
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}

ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style            = CS_HREDRAW | CS_VREDRAW;                                    // объем памяти, выделяемый под структуру
    wcex.lpfnWndProc    = WndProc;                                                    // адрес функции обработки сообщений
    wcex.cbClsExtra        = 0;                                                        // дополнительные байты после класса
    wcex.cbWndExtra        = 0;                                                        // дополнительные байты после экземпляра окна
    wcex.hInstance        = hInstance;                                                // экземпляр приложения
    wcex.hIcon            = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_LAB_1));            // иконка приложения
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);                                // курсор в приложении (его вид)
    wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);                                    // цвет фона
    wcex.lpszMenuName    = MAKEINTRESOURCE(IDC_LAB_1);                                // "имя" меню
    wcex.lpszClassName    = szWindowClass;                                            // имя класса окна
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));        // уменьшенная иконка приложения
    return RegisterClassEx(&wcex);
}

// Инициализация/создание окна, с рядом указанных параметров
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd,hPanel,hBtn[cnt],hDCWnd;
   hInst = hInstance; // cохранить дескриптор экземпляра в глобальной переменной

   // создание главной "формы" программы
   DWORD WndStyle = WS_OVERLAPPED|WS_CAPTION|WS_MINIMIZEBOX|WS_SYSMENU;  // есть заголовок, ограничение размера формы, блок кнопки "на весь экран" 
   hWnd = CreateWindow(szWindowClass, L"Лабораторная №1", WndStyle, CW_USEDEFAULT, 0, 1024, 720, NULL, NULL, hInstance, NULL);

   // создание панели
   DWORD dwExStyle = WS_EX_CLIENTEDGE|WS_EX_DLGMODALFRAME;                        // бордюр + "объем" панели
   DWORD dwStyle   = WS_CHILD|WS_VISIBLE|SS_CENTER|SS_CENTERIMAGE|SS_SUNKEN;    // дочерний, видимый, текст по центру объекта
   hPanel = CreateWindowEx(dwExStyle, L"STATIC", L"", dwStyle, 0, 0, 133, 672, hWnd, NULL, hInstance, NULL);

   // формирование кнопок
   // 1. создадим для меток на кнопках двумерный массив строк,
   // содержащих надписи для кнопок 
   int IDPar=10000;
   char **BtnTitles = new char *[7]; 
   BtnTitles[0] = new char [5];
   BtnTitles[0] = "Линия";
   BtnTitles[1] = new char [13];
   BtnTitles[1] = "Прямоугольник";
   BtnTitles[2] = new char [11];
   BtnTitles[2] = "Треугольник";
   BtnTitles[3] = new char [4];
   BtnTitles[3] = "Круг";
   BtnTitles[4] = new char [5];
   BtnTitles[4] = "Кисть";
   BtnTitles[5] = new char [6];
   BtnTitles[5] = "Ластик";
   BtnTitles[6] = new char [4];
   BtnTitles[6] = "Цвет";  
   // 2. теперь проинициализируем кнопки, и дадим им надписи и номера действий, с помощью класса
   for(int i=0; i<cnt; i++)
   {
       // задаем номер операции для кнопки, через метод, определенный в классе
       int OpNumber=i;
       Button[i].SetAction(OpNumber);
       // задаем title кнопки, указанного в классе
       Button[i].SetTitle(BtnTitles[i]);
       char *title=Button[i].GetTitle();
       // переведем текст из char* в LPCWSTR, чтобы текст был виден корректно, а не виде иероглифов
       WCHAR str[15];
       MultiByteToWideChar(0,0,title,15,str,15);
       //MultiByteToWideChar(0,0,BtnTitles[i],15,str,15);
       LPCWSTR corrected_title = str;
       // создаем кнопку
       hBtn[i] = CreateWindow(L"Button",(LPCWSTR)corrected_title,WS_TABSTOP|WS_VISIBLE|WS_CHILD|BS_DEFPUSHBUTTON,
                                10, 10+35*i, 115, 30, hWnd, (HMENU)IDPar, hInstance, NULL); 
       IDPar++;
   } 

   if (!hWnd) {return FALSE;}
   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);
   return TRUE;
}

// Обработка сообщений, принятых от функции _tWinMain(...)
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;

    ps.rcPaint.bottom=49;
    ps.rcPaint.left=134;
    // каждую итерацию цикла проверяется очередь сообщений приложения. 
    // И если в очереди сообщений есть сообщение, то оно вытаскивается из очереди.
    switch(message)
    {
        // разбор команды
        case WM_COMMAND:
            // реакция на нажатие одной из кнопок
            switch(LOWORD(wParam))
            {
                //рисование линии
                case 10000: 
                    int cntPT=0;
                    POINT begin,end;
                    HDC hDC = ::GetDC(hWnd);
                    HPEN hPen = CreatePen(PS_SOLID, 3, RGB(128, 128, 0));
                    while(WM_LBUTTONDOWN && cnt!=2)
                    {
                        switch(cnt)
                        {
                            case 0:
                                begin.x = LOWORD(lParam); //x
                                begin.y = HIWORD(lParam); //y
                                break;
                            case 1:
                                end.x = LOWORD(lParam);      //x
                                end.y = HIWORD(lParam);      //y
                                break;
                        }
                    }
                    DrawLine(hDC,begin.x,begin.y,end.x,end.y);
                    InvalidateRect(hWnd,NULL,1);
                    ::ReleaseDC(hWnd,hDC);
                    break; /*
                case 10001: 
                    break;
                case 10002: 
                    break;
                case 10003: 
                    break;
                case 10004: 
                    break;
                case 10005: 
                    break;
                case 10006: 
                    break; */
            }
            // получаем параметры
            wmId    = LOWORD(wParam);
            wmEvent = HIWORD(wParam);
            // Выбор в меню:
            switch(wmId)
            {
                // нажали "Справка"
                case IDM_ABOUT:
                    DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                    break;
                // нажали "Сохранить"
                // нажали "Выход"
                case IDM_EXIT:
                    DestroyWindow(hWnd);
                    break;
                default: return DefWindowProc(hWnd, message, wParam, lParam);
            }
            break;
        // отображение формы
        case WM_PAINT:
            hdc = BeginPaint(hWnd, &ps);
            EndPaint(hWnd, &ps);
            break;
        // закрытие формы
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default: return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// Обработчик сообщений для окна "О программе".
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    // проверяем очередь сообщений
    switch (message)
    {
        // если вызвано окно через меню, то его "отрисуем"
        case WM_INITDIALOG:
            return (INT_PTR)TRUE;
        // если же, нажат ESC или кнопка "ОК", то закрываем окно
        case WM_COMMAND:
            if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
            {
                EndDialog(hDlg, LOWORD(wParam));
                return (INT_PTR)TRUE;
            }
        break;
    }
    return (INT_PTR)FALSE;
}

// рисование линии
BOOL DrawLine(HDC hdc, int x1, int y1, int x2, int y2)
{
  POINT pt;
  MoveToEx(hdc, x1, y1, &pt);
  return LineTo(hdc, x2, y2);
}




Это сообщение отредактировал(а) Relrin - 5.9.2012, 16:01
PM MAIL   Вверх
Dem_max
Дата 5.9.2012, 16:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1780
Регистрация: 12.4.2007

Репутация: 16
Всего: 39



прикрепляй архив со всеми .cpp и .h которые ты создаешь, попробую подправить весь проект


--------------------
Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte")
PM MAIL   Вверх
Relrin
Дата 5.9.2012, 16:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 20.2.2012

Репутация: нет
Всего: нет



Цитата(Dem_max @ 5.9.2012,  16:18)
прикрепляй архив со всеми .cpp и .h которые ты создаешь, попробую подправить весь проект

Вот тут код. Писал в Visual Studio 2010

Добавлено через 11 минут и 43 секунды
Отрисовку можно сделать так(рабочий, только написал и опробовал):

Код

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;

    ps.rcPaint.bottom=49;
    ps.rcPaint.left=134;
    // каждую итерацию цикла проверяется очередь сообщений приложения. 
    // И если в очереди сообщений есть сообщение, то оно вытаскивается из очереди.
    switch(message)
    {
        // разбор команды
        case WM_COMMAND:
            // реакция на нажатие одной из кнопок
            switch(LOWORD(wParam))
            {
                case 10000: 
                    NowOp=true;
                    ActionNumb=0;
                    break; 
                case 10001:
                    NowOp=true;
                    ActionNumb=1;
                    break; /*
                case 10002: 
                    break;
                case 10003: 
                    break;
                case 10004: 
                    break;
                case 10005: 
                    break;
                case 10006: 
                    break; */
            }
            // получаем параметры
            wmId    = LOWORD(wParam);
            wmEvent = HIWORD(wParam);
            // Выбор в меню:
            switch(wmId)
            {
                // нажали "Справка"
                case IDM_ABOUT:
                    DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                    break;
                // нажали "Сохранить"
                // нажали "Выход"
                case IDM_EXIT:
                    DestroyWindow(hWnd);
                    break;
                default: return DefWindowProc(hWnd, message, wParam, lParam);
            }
            break;
        // обработка нажатия клавиши
        case WM_LBUTTONDOWN:
            // если нужно что-либо рисовать
            if(NowOp==true)
            {
                begin.x = LOWORD(lParam); 
                begin.y = HIWORD(lParam);
            }
            break;
        case WM_LBUTTONUP:
            // если нужно что-либо рисовать
            if(NowOp==true)
            {
                end.x = LOWORD(lParam);
                end.y = HIWORD(lParam);
                hdc = GetDC(hWnd);
                switch(ActionNumb)
                {
                    // линия
                    case 0:
                        DrawLine(hdc,begin.x,begin.y,end.x,end.y);
                        break;
                    // прямоугольник
                    case 1:
                        DrawRectangle(hdc,begin.x,begin.y,end.x,end.y);
                        break;
                }
                ReleaseDC(hWnd, hdc);    
            }
            break;
        // отображение формы
        case WM_PAINT:
            hdc = BeginPaint(hWnd, &ps);
            EndPaint(hWnd, &ps);
            break;
        // закрытие формы
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default: return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}


Присоединённый файл ( Кол-во скачиваний: 2 )
Присоединённый файл  Code.rar 6,13 Kb
PM MAIL   Вверх
Relrin
Дата 5.9.2012, 17:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 20.2.2012

Репутация: нет
Всего: нет



Хочется еще заодно уточнить, как сделать, чтобы я видел, что я рисую?
PM MAIL   Вверх
Relrin
Дата 5.9.2012, 18:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 20.2.2012

Репутация: нет
Всего: нет



case WM_MOUSEMOVE добавил, чтобы видеть перерисовку, пока веду мышкой. Приче до switch(message) добавил ограничение по окну, которое надо обновлять:
Код

    RECT rect;
    rect.left=133;
    rect.top=0;
    rect.right=1024;
    rect.bottom=682;

Почему я не вижу перерисовки? Может подскажет кто?

Код

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;

    RECT rect;
    rect.left=133;
    rect.top=0;
    rect.right=1024;
    rect.bottom=682;
    // каждую итерацию цикла проверяется очередь сообщений приложения. 
    // И если в очереди сообщений есть сообщение, то оно вытаскивается из очереди.
    switch(message)
    {
        // разбор команды
        case WM_COMMAND:
            // реакция на нажатие одной из кнопок
            switch(LOWORD(wParam))
            {
                case 10000:        // линия
                    NowOp=true;
                    ActionNumb=0;
                    break; 
                case 10001:           // прямоугольник
                    NowOp=true;
                    ActionNumb=1;
                    break; 
                case 10002:           // треугольник
                    NowOp=true;
                    ActionNumb=2;
                    break;  
                case 10003:           // круг
                    NowOp=true;
                    ActionNumb=3;
                    break; 
                case 10004:           // кисть
                    Brush=true;
                    NowOp=true;
                    ActionNumb=4;
                    break;
                case 10005:           // ластик
                    NowOp=true;
                    ActionNumb=5;
                    break;
                case 10006:           // цвет
                    NowOp=true;
                    ActionNumb=6;
                    break;
            }
            // получаем параметры
            wmId    = LOWORD(wParam);
            wmEvent = HIWORD(wParam);
            // Выбор в меню:
            switch(wmId)
            {
                // нажали "Справка"
                case IDM_ABOUT:
                    DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                    break;
                // нажали "Сохранить"
                // нажали "Выход"
                case IDM_EXIT:
                    DestroyWindow(hWnd);
                    break;
                default: return DefWindowProc(hWnd, message, wParam, lParam);
            }
            break;
        // обработка нажатия клавиши
        case WM_LBUTTONDOWN:
            // если нужно что-либо рисовать
            if(NowOp==true)
            {
                begin.x = LOWORD(lParam); //x
                begin.y = HIWORD(lParam); //y
            }
            break;
        case WM_LBUTTONUP:
            // если нужно что-либо рисовать
            if(NowOp==true)
            {
                end.x = LOWORD(lParam);   //x
                end.y = HIWORD(lParam);   //y
                hdc = GetDC(hWnd);
                // если кисть еще доступна
                switch(ActionNumb)
                    {
                        // линия
                        case 0:
                            NowOp=false;
                            Button[0].Action(hdc,0,begin,end);
                            break;
                        // прямоугольник
                        case 1:
                            NowOp=false;
                            Button[1].Action(hdc,1,begin,end);
                            break;
                        // треугольник 
                        case 2:    
                            NowOp=false;
                            Button[2].Action(hdc,2,begin,end);
                            break;
                        // круг
                        case 3:
                            NowOp=false;
                            Button[3].Action(hdc,3,begin,end);
                            break;
                        // кисть
                        // ластик
                        // цвет
                    }
                ReleaseDC(hWnd, hdc);    
            }
            break;
        case WM_MOUSEMOVE:
            InvalidateRect(hWnd,&rect,false);
            break;
        // отображение формы
        case WM_PAINT:
            hdc = BeginPaint(hWnd, &ps);
            EndPaint(hWnd, &ps);
            break;
        // закрытие формы
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default: return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}


Это сообщение отредактировал(а) Relrin - 5.9.2012, 18:41
PM MAIL   Вверх
GremlinProg
Дата 6.9.2012, 08:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Relrin, рисовать нужно в WM_PAINT, а не в WM_LBUTTONUP


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
feodorv
Дата 6.9.2012, 11:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 9
Всего: 45



Цитата(GremlinProg @  6.9.2012,  09:46 Найти цитируемый пост)
Relrin, рисовать нужно в WM_PAINT, а не в WM_LBUTTONUP

Должно быть, пример взят отсюда: Рисование мышью smile 



--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
GremlinProg
Дата 6.9.2012, 12:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(feodorv @  6.9.2012,  13:47 Найти цитируемый пост)
Должно быть, пример взят отсюда: Рисование мышью  

значит, это плохой пример  smile 

пойдет для обучения, но не на практике


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0570 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.