PDA

Просмотр полной версии : C++ граф. задача нужна помощь


Visor
21.05.2007, 00:37
Здравствуйте, уважаемые участники форума. Получил вот такое задание, но возникли проблемы...
Программа Win32 для рисования на экране прямых линий. Начало и конец линии задаются двумя последовательными нажатиями на левую кнопку мыши в основном окне программы. Нажатие на правую очищает экран. Также должен автоматически очищаться через время t после рисования последней линии. Добиться сохранения рисунка при помощи memory bitmaps после перекрытия окна лругими окнами.
При выборе свойства линии, программа должна вывести диал. окно. в checkbox выбираем тип (штриховая или сплошная). А radio buttons для цветов.
Таймаут - тут задается t.
Выход - запрашивает о выходе, и при утвердительном ответе обновить в ini-файле все параметры (тип линии, время таймаута), после этого завершить работу. При повторном запуске, программа загрузит сохраненные параметры из ini-файла.
Проблема в том, что программа виснет при выборе дочернего элемента в гл. меню. Кроме того она не рисует штриховые линии :confused: . Я пробовал менят время задержки, последовательно комментировать те или иные функции и пр., с отладчиком. Ничего. Мне кажется, что дело в WM_PAINT. Иногда получалось по-отдельности включать нужные функции, но все вместе - никогда не работало. :( Сам над этим уже два месяца голову ломаю, ничего не могу сделать.
Если совсем никак, то можете удалить пост или не смотреть вообще.
С меня много плюсиков, если получится!
Проект (включая resource.h и пр.) для MSVS 2005 выложил тут (http://www.4shared.com/file/16324859/870e1c11/Task6.html) в *.rar
А вот то нечто, что мне удалось написать:

#include <windows.h>
#include <stdio.h>
#include "resource.h"
#define TIMER_ID 1

HINSTANCE hhh;

int dedit=5;
int colornumber=1;
bool linestyle=false;
bool startline=true;
bool t=false;
int x,y,x0,y0;

HPEN pen;

LRESULT CALLBACK WindowFunc(HWND,UINT,WPARAM,LPARAM);

//-------------------------------------------------------------------
// WinMain
//-------------------------------------------------------------------
int WINAPI WinMain (HINSTANCE hThisInst,
HINSTANCE hPrevInst,
LPSTR lpszArgs,
int nWinMode)
{
char szWinName[] = "класс окна";
MSG msg;
HWND hwnd;
WNDCLASS wcl;

hhh=hThisInst;

// класс окна
wcl.hInstance = hThisInst; //идентификатор приложения
wcl.lpszClassName = szWinName; //имя класса окна
wcl.lpfnWndProc = WindowFunc; //функция окна
wcl.style = 0; // стиль по умолчанию
wcl.hIcon = LoadIcon(NULL,IDI_APPLICATION); //стандартная иконка
wcl.hCursor = LoadCursor(NULL,IDC_ARROW); //стандартный курсор мыши
wcl.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1); //без меню
wcl.cbClsExtra = 0;
wcl.cbWndExtra = 0;
wcl.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH); // Цвет фона окна

if (!RegisterClass (&wcl)) return 0;

// CreateWindow
hwnd = CreateWindow(szWinName,"Мое первое оконо",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, // горизонтальное положение окна
CW_USEDEFAULT, // вертикальное положение окна
CW_USEDEFAULT, // ширина окна
CW_USEDEFAULT, // высота окна
HWND_DESKTOP,
NULL,
hThisInst,
NULL);

// Показать окно и нарисовать содержимое
ShowWindow(hwnd,nWinMode);

// Цикл обработки сообщений
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}

return msg.wParam;
}

//-------------------------------------------------------------------

//диалоговое окно

BOOL CALLBACK DialogProcTime(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{ char str[10];
switch (uMsg)
{
case WM_INITDIALOG:
sprintf(str,"%d",dedit);
SetDlgItemText(hDlg,IDC_EDIT1,str);
return TRUE;
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:
GetDlgItemText(hDlg,IDC_EDIT1,str,10);
dedit = atoi(str);
EndDialog(hDlg,TRUE);
return TRUE;
break;
case IDCANCEL:
EndDialog(hDlg,TRUE);
return TRUE;
break;
}
break;
}
return FALSE;
}



//диалоговое окно

BOOL CALLBACK DialogProcSvoistva(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
/*
switch (uMsg)
{
case (WM_INITDIALOG):
CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO5, IDC_RADIO1+colornumber-1);
if (linestyle)
CheckDlgButton(hDlg, IDC_CHECK1, BST_CHECKED);
else
CheckDlgButton(hDlg, IDC_CHECK1, BST_UNCHECKED);
return TRUE;
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:
if (IsDlgButtonChecked(hDlg, IDC_RADIO1))
colornumber=1;
if (IsDlgButtonChecked(hDlg, IDC_RADIO2))
colornumber=2;
if (IsDlgButtonChecked(hDlg, IDC_RADIO3))
colornumber=3;
if (IsDlgButtonChecked(hDlg, IDC_RADIO4))
colornumber=4;
if (IsDlgButtonChecked(hDlg, IDC_RADIO5))
colornumber=5;
if (IsDlgButtonChecked(hDlg, IDC_CHECK1))
linestyle=true;
else
linestyle=false;
EndDialog(hDlg,TRUE);
return TRUE;
break;
case IDCANCEL:
EndDialog(hDlg,TRUE);
return TRUE;
break;
}
break;
}
*/
return FALSE;
}



// Функция - обработчик сообщений окна
//-------------------------------------------------------------------
LRESULT CALLBACK WindowFunc(HWND hwnd,UINT message,
WPARAM wParam,LPARAM lParam)
{
PAINTSTRUCT ps;
HDC dc;
HPEN blackpen,whitepen,redpen,greenpen,bluepen;



switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
break;

case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_EXIT:
if (MessageBox(hwnd,"Действительно ли вы хотите выйти?","",MB_OKCANCEL)==IDOK)
{
PostQuitMessage(0);
}
break;
case ID_TIMEOUT:
DialogBox(hhh,MAKEINTRESOURCE(IDD_DIALOG1),hwnd,Di alogProcTime);
break;
case ID_SVOISTVA:
DialogBox(hhh,MAKEINTRESOURCE(IDD_DIALOG2),hwnd,Di alogProcSvoistva);
break;
}
break;
case WM_PAINT:
if (t)
{
dc=BeginPaint(hwnd, &ps);
if (startline)
{
x0=x;
y0=y;
startline=false;
}
else
{

blackpen=CreatePen(PS_SOLID,2,RGB(0,0,0));
whitepen=CreatePen(PS_SOLID,2,RGB(255,255,255));
redpen=CreatePen(PS_SOLID,2,RGB(255,0,0));
greenpen=CreatePen(PS_SOLID,2,RGB(0,255,0));
bluepen=CreatePen(PS_SOLID,2,RGB(0,0,255));
if (colornumber==1) SelectObject(dc,blackpen);
if (colornumber==2) SelectObject(dc,whitepen);
if (colornumber==3) SelectObject(dc,redpen);
if (colornumber==4) SelectObject(dc,greenpen);
if (colornumber==5) SelectObject(dc,bluepen);
MoveToEx(dc, x0, y0, NULL);
LineTo(dc, x, y);
startline=true;
SetTimer(hwnd,TIMER_ID,1000*dedit,NULL);
}
EndPaint(hwnd, &ps);
}
break;
case WM_LBUTTONDOWN :
x=LOWORD(lParam);
y=HIWORD(lParam);
t=true;
InvalidateRect(hwnd,0,FALSE);
UpdateWindow(hwnd);
break;
case WM_RBUTTONDOWN :
t=false;
InvalidateRect(hwnd,0,TRUE);
UpdateWindow(hwnd);
startline=true;
break;
case WM_TIMER:
KillTimer(hwnd,TIMER_ID);
t=false;
InvalidateRect(hwnd,0,TRUE);
UpdateWindow(hwnd);
break;

default:
return DefWindowProc (hwnd, message, wParam, lParam);
}

return 0;
}
Спасибо заранее, если посмотрите, так как в C++ я совсем чайник.

nerezus
21.05.2007, 07:14
Тебе обязательно на апях?

Visor
21.05.2007, 10:49
да, вообще задача поставлена именно для выполнения в windows api

hidden
21.05.2007, 11:09
Сейчас времени уже нету, позже посмотрю внимательнее.
Она кстати у тебя не виснет, просто создаёт диалог но фокус на него не передаёт(без нажатия alt), похоже что фокус остаётся у меню бара, почему я так и не понял...

1) Тело функции обработки диалога зря закоментил.
2) return TRUE не везде возвращяешь.

Visor
21.05.2007, 12:21
Да, вижу, только вот не понимаю, в чем дело с ALTом и что не рисуются штриховые :confused:

hidden
22.05.2007, 02:36
У тебя с проектом что-то не так, я так и не нашел что, создай новый проект, НЕ КОПИРУЙ диалоговые окна, пункты меню и даже их элементы, не копируй свои функции, делай точно как в заготовке проекта и должно всё работать :)

Я пробовал создать новый проект, скопировать туда твой диалог и функцию колбэка и получилась та-же чушь, так что НЕ КОПИРУЙ.

Насчёт пунктиров, так функция CreatePen не умеет рисовать пунктиры шире одного пикселя, вроде-бы ExtCreatePen умеет или используй "GDI Plus"

scrat
22.05.2007, 19:00
блин писал графы правда не win api если понадобяться какие-нить алгоритмы стучи в 213947843 помогу

Visor
22.05.2007, 20:44
Респект! :)
Вобщем, с текстом можно так, насколько я понял:

void CTextWnd::OnPaint()
{
CPaintDC dc(this);
dc.SetTextColor(clrText);
dc.SetBkColor(::GetSysColor(COLOR_WINDOW));
CRect rect;
GetClientRect(rect);
dc.DrawText(_TEXT("Обработка WM_PAINT"), -1, rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER);
}

Вот. Что касается нетекстовых элементов, то, видимо нужно использовать memory bitmaps (как-то :confused: ). То есть можно и без этого, но если графики много, всё же оно целесообразно.
Насчёт пунктиров, так функция CreatePen не умеет рисовать пунктиры шире одного пикселя, вроде-бы ExtCreatePen умеет или используй "GDI Plus"
Странно, вроде если брать CreatePen, то можно пользоваться либо PS_SOLID, либо PS_DASH.
Или я тут что-то напутал с CreatePen и ExtCreatePen.

P.S. Половину дня убил на поиски ресурсов по теме.
Нашёл вот эту статью (http://forum.antichat.ru/thread26842-wm_paint.html) -- вполне информативно!
Ладно, я ещё покопаюсь. Надеюсь, всё же озарение будет :) -- тогда обязательно отпишусь!

hidden
22.05.2007, 21:19
Странно, вроде если брать CreatePen, то можно пользоваться либо PS_SOLID, либо PS_DASH.
Или я тут что-то напутал с CreatePen и ExtCreatePen.http://msdn2.microsoft.com/en-us/library/aa922162.aspxIf the value specified by nWidth is greater than 1, the fnPenStyle parameter must be PS_NULL or PS_SOLID.