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