C++ граф. задача нужна помощь

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by Visor, 21 May 2007.

  1. Visor

    Visor New Member

    Joined:
    4 Jun 2006
    Messages:
    26
    Likes Received:
    3
    Reputations:
    3
    Здравствуйте, уважаемые участники форума. Получил вот такое задание, но возникли проблемы...
    Программа Win32 для рисования на экране прямых линий. Начало и конец линии задаются двумя последовательными нажатиями на левую кнопку мыши в основном окне программы. Нажатие на правую очищает экран. Также должен автоматически очищаться через время t после рисования последней линии. Добиться сохранения рисунка при помощи memory bitmaps после перекрытия окна лругими окнами.
    При выборе свойства линии, программа должна вывести диал. окно. в checkbox выбираем тип (штриховая или сплошная). А radio buttons для цветов.
    Таймаут - тут задается t.
    Выход - запрашивает о выходе, и при утвердительном ответе обновить в ini-файле все параметры (тип линии, время таймаута), после этого завершить работу. При повторном запуске, программа загрузит сохраненные параметры из ini-файла.
    Проблема в том, что программа виснет при выборе дочернего элемента в гл. меню. Кроме того она не рисует штриховые линии :confused: . Я пробовал менят время задержки, последовательно комментировать те или иные функции и пр., с отладчиком. Ничего. Мне кажется, что дело в WM_PAINT. Иногда получалось по-отдельности включать нужные функции, но все вместе - никогда не работало. :( Сам над этим уже два месяца голову ломаю, ничего не могу сделать.
    Если совсем никак, то можете удалить пост или не смотреть вообще.
    С меня много плюсиков, если получится!
    Проект (включая resource.h и пр.) для MSVS 2005 выложил тут в *.rar
    А вот то нечто, что мне удалось написать:
    Code:
    #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,DialogProcTime);               	
    			break;
    		 case ID_SVOISTVA:			
    			    DialogBox(hhh,MAKEINTRESOURCE(IDD_DIALOG2),hwnd,DialogProcSvoistva);				
    			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++ я совсем чайник.
     
    #1 Visor, 21 May 2007
    Last edited: 22 May 2007
  2. nerezus

    nerezus Banned

    Joined:
    12 Aug 2004
    Messages:
    3,191
    Likes Received:
    729
    Reputations:
    266
    Тебе обязательно на апях?
     
  3. Visor

    Visor New Member

    Joined:
    4 Jun 2006
    Messages:
    26
    Likes Received:
    3
    Reputations:
    3
    да, вообще задача поставлена именно для выполнения в windows api
     
  4. hidden

    hidden 7H3 0N3

    Joined:
    23 Apr 2006
    Messages:
    550
    Likes Received:
    332
    Reputations:
    386
    Сейчас времени уже нету, позже посмотрю внимательнее.
    Она кстати у тебя не виснет, просто создаёт диалог но фокус на него не передаёт(без нажатия alt), похоже что фокус остаётся у меню бара, почему я так и не понял...

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

    Visor New Member

    Joined:
    4 Jun 2006
    Messages:
    26
    Likes Received:
    3
    Reputations:
    3
    Да, вижу, только вот не понимаю, в чем дело с ALTом и что не рисуются штриховые :confused:
     
    #5 Visor, 21 May 2007
    Last edited: 22 May 2007
  6. hidden

    hidden 7H3 0N3

    Joined:
    23 Apr 2006
    Messages:
    550
    Likes Received:
    332
    Reputations:
    386
    У тебя с проектом что-то не так, я так и не нашел что, создай новый проект, НЕ КОПИРУЙ диалоговые окна, пункты меню и даже их элементы, не копируй свои функции, делай точно как в заготовке проекта и должно всё работать :)

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

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

    scrat кодер

    Joined:
    8 Apr 2007
    Messages:
    625
    Likes Received:
    541
    Reputations:
    3
    блин писал графы правда не win api если понадобяться какие-нить алгоритмы стучи в 213947843 помогу
     
    1 person likes this.
  8. Visor

    Visor New Member

    Joined:
    4 Jun 2006
    Messages:
    26
    Likes Received:
    3
    Reputations:
    3
    Респект! :)
    Вобщем, с текстом можно так, насколько я понял:
    Code:
    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, то можно пользоваться либо PS_SOLID, либо PS_DASH.
    Или я тут что-то напутал с CreatePen и ExtCreatePen.

    P.S. Половину дня убил на поиски ресурсов по теме.
    Нашёл вот эту статью -- вполне информативно!
    Ладно, я ещё покопаюсь. Надеюсь, всё же озарение будет :) -- тогда обязательно отпишусь!
     
    #8 Visor, 22 May 2007
    Last edited: 22 May 2007
  9. hidden

    hidden 7H3 0N3

    Joined:
    23 Apr 2006
    Messages:
    550
    Likes Received:
    332
    Reputations:
    386
    http://msdn2.microsoft.com/en-us/library/aa922162.aspx