1 //Prak2 MFC ohne Assistenten

2 //Author: Steve Moser

3 //Email: smoser@anno74.de

4 //Datum: 20.10.2003

5 
6 
7 
8 //***********************************************************************
9 // kritzel.cpp: Definition der Implementierung der Klassen
10 //***********************************************************************

11 #define OEMRESOURCE

12 
13 #include <afxwin.h> // Globale Header-Datei

14 #include "kritzel.h"

15 #include "resource.h"

16 
17 #define VHEIGHT	1000

18 #define HWIDTH	800

19 
20 
21 CMyApp myApp;
22 
23 // CMyApp member functions

24 BOOL CMyApp::InitInstance ()
25 {
26     m_pMainWnd = new CHauptFenster;			//membervariable von CWinApp legt objekt von CHauptfenster an-->ruft konstruktor CHauptFenster auf

27     m_pMainWnd->ShowWindow (m_nCmdShow);
28     m_pMainWnd->UpdateWindow ();
29     return TRUE;
30 }
31 
32 
33 //************************************************************************
34 // CMainWindow message map and member functions
35 BEGIN_MESSAGE_MAP (CHauptFenster, CFrameWnd)								// klasse, fuer die die messagemap ist und die klasse, von der sie abgeleitet ist
36 ON_COMMAND (IDM_FILE_NEW,OnFileNew)											//OnCommand Nachrichten werden hier mit den selbsterstellten funktion verknüpft
37 ON_COMMAND (IDM_FILE_EXIT,OnExit)
38 ON_COMMAND_RANGE (IDM_BREITE_KRASSDUENN, IDM_BREITE_SEHR_DICK, OnBreite )	//von krassduenn - sehrdick wird OnBreite() aufgerufen

39 ON_COMMAND_RANGE (IDM_FARBE_SCHWARZ, IDM_FARBE_GRUEN, OnFarbe )
40 ON_COMMAND_RANGE (IDM_FIGUR_LINIE, IDM_FIGUR_ELLIPSE, OnFigur )
41 
42 ON_UPDATE_COMMAND_UI_RANGE (IDM_BREITE_KRASSDUENN, IDM_BREITE_SEHR_DICK, OnUpdateBreiteUI ) //wird bei neuzeichnen des menues aufgerufen

43 ON_UPDATE_COMMAND_UI_RANGE (IDM_FARBE_SCHWARZ, IDM_FARBE_GRUEN, OnUpdateFarbeUI )
44 ON_UPDATE_COMMAND_UI_RANGE (IDM_FIGUR_LINIE, IDM_FIGUR_ELLIPSE, OnUpdateFigurUI )
45 
46 ON_WM_CREATE ()			//nachricht wird erzeugt nachdem das fenster kreirt wurde, aber noch nicht sichtbar ist
47 ON_WM_MEASUREITEM ()	//wird ein oberpunkt eines menues aufgerufen, wird diese nachricht erzeugt
48 ON_WM_DRAWITEM ()		//wird in das untermenue gewechselt, wird über diese funktion das menue gezeichnet
49 
50 END_MESSAGE_MAP ()
51 
52 //*************************************************************************************
53 //Function: CHauptFenster() ;Konstruktor
54 //Return value:
55 //description: initialisiert hauptfenster und dessen eigenschaften, + menueerzeugung + standartwerte
56 //*************************************************************************************

57 CHauptFenster::CHauptFenster () //Konstruktor

58 {
59     CString str= AfxRegisterWndClass(0,
60                                      myApp.LoadStandardCursor (IDC_CROSS),
61                                      (HBRUSH) (COLOR_WINDOW + 1),
62                                      myApp.LoadIcon (IDR_HAUPTMENUE));
63 
64     Create (str, "Kritzelprogramm" ,WS_OVERLAPPEDWINDOW, rectDefault,NULL, MAKEINTRESOURCE (IDR_HAUPTMENUE )  );//da von CFrameWnd abgeleitet. beschreibt, wie fenster beschaffen ist

65     LoadAccelTable(MAKEINTRESOURCE(IDR_HAUPTMENUE) );
66     CMenu* pMenu = GetMenu();
67     for(int i=0;i<5;i++)
68     {
69         pMenu->ModifyMenu(IDM_FARBE_SCHWARZ+i,MF_BYCOMMAND | MF_OWNERDRAW, IDM_FARBE_SCHWARZ+i);
70     }
71 
72     m_farbe		= IDM_FARBE_SCHWARZ;
73     m_breite		= IDM_BREITE_KRASSDUENN;
74     m_figur		= IDM_FIGUR_LINIE;
75 
76 
77 }
78 
79 //*************************************************************************************
80 //Function: OnCreate ()
81 //Return value: int
82 //description: erzeugt eine view und verbindet diese mit dem hauptfenster
83 //*************************************************************************************

84 int CHauptFenster :: OnCreate (LPCREATESTRUCT lpcs)
85 {
86     if (CFrameWnd::OnCreate(lpcs) ==-1)// aufruf der basisklassenfunktion zuerst

87         return -1;
88 
89     m_pMyView = new CMyView;
90     m_pMyView->Create ( NULL, NULL, WS_CHILD | WS_VISIBLE, CRect (0,0,0,0), this, AFX_IDW_PANE_FIRST, NULL);
91     //CRect ist null, weil childfenster automatisch an mainfenster angepasst wird ueber AFX_IDW_PANE_FIRST

92     //ON_CREATE message wird erst abgesetzt, NACHDEM das fenster generiert wurde, aber noch nicht sichtbaer ist

93 
94     return 0;
95 }
96 
97 //*************************************************************************************
98 //Function: Array
99 //Return value: none
100 //description: initialisiert 5 farbwerte
101 //*************************************************************************************

102 const COLORREF CHauptFenster :: crColors[5]=
103     {
104         RGB(0,0,0),
105         RGB(255,0,0),
106         RGB(0,0,255),
107         RGB(255,255,0),
108         RGB(0,255,0)
109     };
110 //*************************************************************************************
111 //Function: Array
112 //Return value:none
113 //description: initialisiert 6 breitenwerte zur verwendung mit einem stift (Pen)
114 //*************************************************************************************

115 const UINT CHauptFenster::uiBreite[6]=
116     {
117         1,
118         8,
119         16,
120         24,
121         32,
122         64
123     };
124 
125 //*************************************************************************************
126 //Function: OnMeasureItem()
127 //Return value: void
128 //description: legt die dimension fest eines menueeintrages fest
129 //*************************************************************************************

130 void CHauptFenster :: OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpmis)
131 {
132     lpmis->itemWidth= ::GetSystemMetrics(SM_CYMENU)*4;
133     lpmis->itemHeight= ::GetSystemMetrics(SM_CYMENU);
134 }
135 
136 //*************************************************************************************
137 //Function: OnDrawItem ()
138 //Return value: void
139 //description: zeichnet das untermenue und setzt den auswahlhacken bei den entsprechenden werten
140 //*************************************************************************************

141 void CHauptFenster :: OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpdis)
142 {
143 
144     BITMAP bm;
145     CBitmap bitmap;
146     bitmap.LoadOEMBitmap(OBM_CHECK);
147     bitmap.GetObject(sizeof(bm),&bm);
148 
149     CDC dc;
150     dc.Attach(lpdis->hDC);
151     CBrush* pBrush = new CBrush(::GetSysColor((lpdis->itemState & ODS_SELECTED) ? COLOR_HIGHLIGHT : COLOR_MENU));
152     dc.FrameRect(&(lpdis->rcItem),pBrush);
153     delete pBrush;
154 
155     if(lpdis->itemState & ODS_CHECKED)
156     {
157         CDC dcMem;
158         dcMem.CreateCompatibleDC(&dc);
159         CBitmap* pOldBitmap = dcMem.SelectObject(&bitmap);
160 
161         dc.BitBlt(lpdis->rcItem.left+4,lpdis->rcItem.top + (((lpdis->rcItem.bottom - lpdis->rcItem.top)-bm.bmHeight)/2),bm.bmWidth,bm.bmHeight,&dcMem,0,0,SRCCOPY);
162         dcMem.SelectObject(pOldBitmap);
163     }
164 
165 
166     pBrush = new CBrush (crColors[lpdis->itemID - IDM_FARBE_SCHWARZ]);
167     CRect rect = lpdis->rcItem;
168     rect.DeflateRect(6,4);
169     rect.left+= bm.bmWidth;
170     dc.FillRect(rect,pBrush);
171     delete pBrush;
172     dc.Detach();
173 
174 }
175 
176 //*************************************************************************************
177 //Function: OnFileNew()
178 //Return value: void
179 //description: Zeichenflaeche wird geleert und bereits gespeicherte Objekte geloescht
180 //*************************************************************************************

181 void CHauptFenster :: OnFileNew()
182 {
183     ((CMyView *)((CHauptFenster *)AfxGetApp()->GetMainWnd())->m_pMyView)->pArray.RemoveAll();
184     InvalidateRect(0,true);
185 
186 }
187 
188 //*************************************************************************************
189 //Function: OnExit()
190 //Return value: void
191 //description: Nachricht an das Hauptfenster zum beenden des Programms
192 //*************************************************************************************

193 void CHauptFenster :: OnExit()
194 {
195     SendMessage(WM_CLOSE,0,0);
196 }
197 
198 //*************************************************************************************
199 //Function: OnBreite()
200 //Return value: void
201 //description: setzt neue breite, die ausgewählt wurde (menue) und akt.breite, wird aber
202 // 			noch nicht gezeichnet
203 //*************************************************************************************

204 void CHauptFenster :: OnBreite(UINT ID)
205 {
206     m_breite = ID;
207     m_pMyView->m_akt_breite = uiBreite[ID - IDM_BREITE_KRASSDUENN ];
208 }
209 
210 //*************************************************************************************
211 //Function: OnFarbe()
212 //Return value: void
213 //description:setzt neue farbe, die ausgewählt wurde (menue) und akt.farbe, wird aber
214 // 			noch nicht gezeichnet
215 //*************************************************************************************

216 void CHauptFenster :: OnFarbe(UINT ID)
217 {
218     m_farbe = ID;
219     m_pMyView->m_akt_farbe = crColors[ID - IDM_FARBE_SCHWARZ];
220 }
221 
222 //*************************************************************************************
223 //Function:OnFigur()
224 //Return value: void
225 //description:setzt neue figur, die ausgewählt wurde (menue) und akt.figur, wird aber
226 // 			noch nicht gezeichnet
227 //*************************************************************************************

228 void CHauptFenster :: OnFigur(UINT ID)
229 {
230     m_figur = ID;
231     m_pMyView->m_akt_figur = ID;
232 }
233 
234 //*************************************************************************************
235 //Function: OnUpdateBreiteUI()
236 //Return value: void
237 //description: die funktion setzt nun sichtbar den neuen hacken im auswahlmenue
238 //*************************************************************************************

239 void CHauptFenster::OnUpdateBreiteUI(CCmdUI *pCmdUI)
240 {
241     pCmdUI->SetCheck(pCmdUI->m_nID == m_breite );
242 }
243 
244 //*************************************************************************************
245 //Function: OnUpdateFarbeUI
246 //Return value: void
247 //description: die funktion setzt nun sichtbar den neuen hacken im auswahlmenue
248 //*************************************************************************************

249 void CHauptFenster::OnUpdateFarbeUI(CCmdUI *pCmdUI)
250 {
251     pCmdUI->SetCheck(pCmdUI->m_nID == m_farbe );
252 }
253 
254 //*************************************************************************************
255 //Function: OnUpdateFigurUI
256 //Return value: void
257 //description: die funktion setzt nun sichtbar den neuen hacken im auswahlmenue
258 //*************************************************************************************

259 void CHauptFenster::OnUpdateFigurUI(CCmdUI *pCmdUI)
260 {
261     pCmdUI->SetCheck(pCmdUI->m_nID == m_figur );
262 }
263 
264 
265 //*************************************************************************
266 //CMyView message map und memberfunktionen

267 BEGIN_MESSAGE_MAP (CMyView, CScrollView)
268 ON_COMMAND_RANGE (IDM_BREITE_KRASSDUENN, IDM_BREITE_SEHR_DICK, OnMenuUpdate )
269 ON_COMMAND_RANGE (IDM_FIGUR_LINIE, IDM_FIGUR_ELLIPSE, OnMenuUpdate )
270 
271 ON_WM_SIZE ()
272 ON_WM_LBUTTONDOWN ()
273 ON_WM_LBUTTONUP ()
274 ON_WM_MOUSEMOVE ()
275 ON_WM_CONTEXTMENU ()
276 END_MESSAGE_MAP ()
277 
278 
279 //*************************************************************************************
280 //Function: Konstruktor
281 //Return value:
282 //description: initialisierung der membervariablen dieser klassen,+aktuellen cusor holen
283 //*************************************************************************************

284 CMyView::CMyView()
285 {
286     m_standard=GetCursor();
287 
288     m_akt_breite = 1;
289     m_akt_farbe = RGB(0,0,0);
290     m_akt_figur = IDM_FIGUR_LINIE;
291     m_movement = false;
292     m_locked = false;
293 
294 }
295 
296 //*************************************************************************************
297 //Function: OnSize
298 //Return value: void
299 //description: setzt die scrollmaßen bei erstellung der scrollview, muss vorhanden sein
300 //*************************************************************************************

301 void CMyView::OnSize(UINT nType,int cx, int cy )
302 {
303     SetScrollSizes(MM_TEXT,CSize(VHEIGHT,HWIDTH), CSize (0,10), CSize (0,10) );
304 }
305 
306 //*************************************************************************************
307 //Function: OnDraw
308 //Return value: void
309 //description: view enthält virtuelle funktion OnDraw, zeichnet in verbindung mit der scrollview
310 //			die elemente neu, die in einem array vorher gespeichert wurden, an die geg. pos
311 //			(wird bei verdecken des fensters, oder popup, etc. aufgerufen)
312 //*************************************************************************************

313 void CMyView::OnDraw(CDC* pDC)
314 {
315     mObject *obj;
316     if(!pArray.IsEmpty())
317     {
318         POSITION pos = pArray.GetTailPosition();
319         while( pos )
320         {
321 
322             obj = (mObject*)pArray.GetAt(pos);
323             switch ( obj->sType)
324             {
325             case IDM_FIGUR_LINIE:
326                 {
327                     CPen pen;
328                     pen.CreatePen(PS_SOLID,obj->sBreite,obj->sFarbe);
329                     CPen * p = pDC->SelectObject(&pen);
330                     pDC->MoveTo(obj->sStart);
331                     pDC->LineTo(obj->sEnde);
332                     pDC->SelectObject(p);
333                     break;
334                 }
335             case IDM_FIGUR_RECHTECK:
336                 {
337                     CRect rect(obj->sStart,obj->sEnde);
338                     CBrush brush;
339                     brush.CreateSolidBrush(obj->sFarbe);
340                     pDC->SelectObject( &brush );
341                     pDC->Rectangle(&rect);
342                     break;
343                 }
344             case IDM_FIGUR_ELLIPSE:
345                 {
346                     CRect rect (obj->sStart,obj->sEnde);
347                     CBrush brush;
348                     brush.CreateSolidBrush(obj->sFarbe);
349                     pDC->SelectObject(&brush);
350                     pDC->Ellipse(&rect);
351                     break;
352                 }
353             case IDM_FIGUR_KREIS:
354                 {
355                     CRect rect (obj->sStart,obj->sEnde );
356                     CBrush brush;
357                     brush.CreateSolidBrush(obj->sFarbe);
358                     pDC->SelectObject(&brush);
359                     pDC->Ellipse(&rect);
360                     break;
361                 }
362 
363             default:
364                 break;
365 
366             }
367             pArray.GetPrev(pos);
368         }
369     }
370 }
371 
372 
373 //*************************************************************************************
374 //Function: AddToList
375 //Return value: void
376 //description: fuegt gegebenes objekt zu einem array hinzu, aus LButtonUp aufgerufen
377 //*************************************************************************************

378 void CMyView::AddToList()
379 {
380     mObject *obj = new mObject;
381     obj->sStart = m_start;
382     obj->sEnde = m_ende;
383     obj->sType = m_akt_figur;
384     obj->sFarbe = m_akt_farbe;
385     obj->sBreite = m_akt_breite;
386 
387     pArray.AddHead(obj);
388 
389 
390 }
391 
392 //*************************************************************************************
393 //Function: OnLButtonDown
394 //Return value: void
395 //description: bei druecken der linken maustaste werden cursor und capture enabled
396 //*************************************************************************************

397 void CMyView::OnLButtonDown (UINT nFlags, CPoint point)
398 {
399     HCURSOR neu;
400     neu = LoadCursor(NULL,IDC_CROSS);
401     SetCursor(neu);
402 
403     if(!m_locked)
404     {
405         SetCapture();
406         m_locked = true;
407         m_movement = true;
408     }
409     m_start = point;
410     m_ende = point;
411 
412 }
413 
414 //*************************************************************************************
415 //Function: OnLButtonUp
416 //Return value: void
417 //description: zeichnet das aktuelle objekt an gegebenen stellen
418 //*************************************************************************************

419 void CMyView::OnLButtonUp( UINT nFlags,CPoint point)
420 {
421     if(m_movement)
422     {
423         CClientDC dc(this); //gibst du mir werkzeug zum rumschrauben

424         InvertLine(&dc,m_start,m_ende);
425 
426         switch (m_akt_figur)
427         {
428         case IDM_FIGUR_LINIE:
429             {
430                 CPen pen;
431                 pen.CreatePen(PS_SOLID,m_akt_breite,m_akt_farbe);
432                 dc.SelectObject(&pen);
433                 dc.MoveTo(m_start);
434                 dc.LineTo(point);
435                 break;
436             }
437         case IDM_FIGUR_RECHTECK:
438             {
439                 CRect rect(m_start,point);
440                 CBrush brush;
441                 brush.CreateSolidBrush(m_akt_farbe);
442                 dc.SelectObject( &brush );
443                 dc.Rectangle(&rect);
444                 break;
445             }
446         case IDM_FIGUR_ELLIPSE:
447             {
448                 CRect rect (m_start,point);
449                 CBrush brush;
450                 brush.CreateSolidBrush(m_akt_farbe);
451                 dc.SelectObject(&brush);
452                 dc.Ellipse(&rect);
453                 break;
454             }
455         case IDM_FIGUR_KREIS:
456             {
457                 m_ende = MakeQuadrat(point);
458                 CRect rect (m_start, m_ende );
459                 CBrush brush;
460                 brush.CreateSolidBrush(m_akt_farbe);
461                 dc.SelectObject(&brush);
462                 dc.Ellipse(&rect);
463                 break;
464             }
465 
466         default:
467             break;
468         }
469 
470         if(m_locked)
471         {
472             ReleaseCapture();
473             m_locked = false;
474             m_movement = false;
475         }
476 
477 
478     }
479     AddToList();
480     SetCursor(m_standard);
481 }
482 
483 //*************************************************************************************
484 //Function: OnMouseMove
485 //Return value: void
486 //description: solange die Maus bewegt wird, werden alte temporäre linien gelöscht und
487 //			neu gezeichnet ueber den aufruf der InvertLine Methode
488 //*************************************************************************************

489 void CMyView::OnMouseMove( UINT nFlags, CPoint point)
490 {
491     if(m_movement)
492     {
493         CClientDC dc (this);
494         InvertLine(&dc, m_start, m_ende);
495         InvertLine(&dc, m_start, point);
496         m_ende = point;
497     }
498 }
499 
500 //*************************************************************************************
501 //Function: InvertLine
502 //Return value: void
503 //description: löscht und zeichnet eine temporäre figur ohne füllung an geg. koordinaten
504 //*************************************************************************************

505 void CMyView::InvertLine(CDC* pDC, CPoint start, CPoint ende)
506 {
507     int alterZustand = pDC->SetROP2(R2_NOT);
508     switch (m_akt_figur)
509     {
510     case IDM_FIGUR_LINIE:
511         pDC->MoveTo(start);
512         pDC->LineTo(ende);
513         break;
514     case IDM_FIGUR_RECHTECK:
515         {
516             CRect rect (start,ende);
517             pDC->SelectStockObject(NULL_BRUSH);
518             pDC->Rectangle(&rect);
519             break;
520         }
521     case IDM_FIGUR_ELLIPSE:
522         {
523             CRect rect (start,ende);
524             pDC->SelectStockObject(NULL_BRUSH);
525             pDC->Ellipse(&rect);
526             break;
527         }
528     case IDM_FIGUR_KREIS:
529         {
530             CRect rect (m_start,MakeQuadrat(ende) );
531             pDC->SelectStockObject(NULL_BRUSH);
532             pDC->Ellipse(&rect);
533             break;
534         }
535 
536     default:
537         break;
538     }
539     pDC->SetROP2(alterZustand);
540 }
541 
542 //*************************************************************************************
543 //Function: OnContextMenu
544 //Return value: void
545 //description: bei rechter maustaste wird kontextmenue erstellt + setzen der aktuellen auswahl
546 //*************************************************************************************

547 void CMyView :: OnContextMenu (CWnd *pWnd, CPoint pos)
548 {
549     CRect rect;
550     GetClientRect (&rect);
551     ClientToScreen(&rect);
552     if(rect.PtInRect(pos) )
553     {
554         CMenu menue;
555         menue.LoadMenu(IDR_CONTEXTMENU);
556         CMenu* pContextMenue = menue.GetSubMenu(0);
557 
558         pContextMenue->CheckMenuItem( ((CHauptFenster * )AfxGetApp()->GetMainWnd())->m_breite,MF_BYCOMMAND | MF_CHECKED );
559         pContextMenue->CheckMenuItem( ((CHauptFenster * )AfxGetApp()->GetMainWnd())->m_figur,MF_BYCOMMAND | MF_CHECKED );
560 
561         pContextMenue->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON |TPM_RIGHTBUTTON, pos.x, pos.y, this);
562 
563         return;
564     }
565 
566     CWnd::OnContextMenu(pWnd,pos);
567 
568 }
569 
570 //*************************************************************************************
571 //Function: OnMenuUpdate
572 //Return value: void
573 //description: erfolgt im kontextmenue einen neue auswahl wird diese hier mit dem hauptmenue abgeglichen
574 //*************************************************************************************

575 void CMyView::OnMenuUpdate(UINT ID)
576 {
577     if(ID<126)
578         ((CHauptFenster * )AfxGetApp()->GetMainWnd())->OnBreite(ID);
579     else
580         ((CHauptFenster * )AfxGetApp()->GetMainWnd())->OnFigur(ID);
581 }
582 
583 //*************************************************************************************
584 //Function: MakeQuadrat
585 //Return value: CPoint (x,y)
586 //description: gleicht koordinaten ab, um ein quadrat zu erzeugen, das widerrum zur
587 //			erzeugung eines kreises notwendig ist
588 //*************************************************************************************

589 CPoint CMyView::MakeQuadrat(CPoint point)
590 {
591     int wert;
592     CPoint tpoint = point;
593     if( (point.x > m_start.x) && (m_start.y < point.y) )
594     {
595         wert = point.x - m_start.x;
596         tpoint.y = m_start.y + wert;
597     }
598     if( (point.x < m_start.x) && (m_start.y < point.y) )
599     {
600         wert = m_start.x - point.x;
601         tpoint.y = m_start.y + wert;
602     }
603     if( (point.x > m_start.x) && (m_start.y > point.y) )
604     {
605         wert = point.x - m_start.x;
606         tpoint.y = m_start.y - wert;
607     }
608     if( (point.x < m_start.x) && (m_start.y > point.y) )
609     {
610         wert = m_start.x - point.x;
611         tpoint.y = m_start.y - wert;
612     }
613     return tpoint;
614 }


syntax highlighted by Code2HTML, v. 0.9.1