Beim verschieben des Kreises findet kein refresh stat
-
Hallo
ich habe ein Kreis den ich in Größe ändern kann, und den ich bewegen kann. Hier tritt auch der Fehler ein. Jede Bewegung wird gezeichnet, so dass am ende viele Kreise zu sehen sind (siehe Bild).http://www.informatik.fh-wiesbaden.de/~wreid001/prog.jpg
Weiß kein Rat mehr was ich da machen kann.
Bin für jede Hilfe dankbar.
-
Und wie ist das Kreise-Zeichnen implementiert? in der CMyDerivedWnd::OnDraw(..) oder wie, wo, was?
Gruss, Gio
-
Kreis zeichnen geschieht beim mir in der Funktion DrawObject()
void CSplitterTestView::DrawObject(int object) { CDC *pDC; pDC = new CClientDC(this); HDC Ovlhdc = pDC->GetSafeHdc(); switch(object) { case NONE: Invalidate(); UpdateWindow(); break; case CIRCLE: drawcircle(Ovlhdc,true); break; } }hier erzeuge ich ein CClientDC objekt welches ich dann weiter an drawcircle weiter reiche.
void CSplitterTestView::drawcircle(HDC hdc,bool Visible) { if(Visible) { //Lösche altes Objekt: Clipper.right = Clipper.right - 5; Clipper.bottom= Clipper.bottom - 5; //Zeichne neuen Kreis: DrawEllipseWCross(hdc,GraphObject->GetCirclePosInt(0,TablePos).x,GraphObject->GetCirclePosInt(0,TablePos).y,GraphObject->GetCircleRadiusInt(0),Clipper); } else { Invalidate(); UpdateWindow(); } }hier prüfe ich ob ich einen Kreis gemalt hatte oder nicht, in DrawEllipseWCross() setze ich zum malen.
void CSplitterTestView::DrawEllipseWCross(HDC hdc,int CenterX,int CenterY,int radius,RECT Clipper) { //Kreis zeichnen: DrawEllipse(hdc,CenterX,CenterY,radius,Clipper, DrawingColor); // Kreiskreuz wird gezeichnet DrawLine(hdc,CenterX-((int)(radius*CIRCLE_LINE_DISTANCE) /3),CenterY, CenterX+((int)(radius*CIRCLE_LINE_DISTANCE /3)),CenterY, Clipper,ReferencingColor); DrawLine(hdc,CenterX,CenterY-((int)(radius*CIRCLE_LINE_DISTANCE) /3), CenterX,CenterY+((int)(radius*CIRCLE_LINE_DISTANCE) /3), Clipper,ReferencingColor); //Folgendes zeichnet Ein Kreiskreuz mit ausgelassener Mitte: DrawLine(hdc,CenterX-((int)(radius*CIRCLE_LINE_DISTANCE)),CenterY, CenterX-radius+((int)(radius*CIRCLE_LINE_DISTANCE)),CenterY, Clipper, ReferencingColor); DrawLine(hdc,CenterX+((int)(radius*CIRCLE_LINE_DISTANCE)),CenterY, CenterX+radius-((int)(radius*CIRCLE_LINE_DISTANCE)),CenterY, Clipper, ReferencingColor); DrawLine(hdc,CenterX,CenterY-((int)(radius*CIRCLE_LINE_DISTANCE)), CenterX,CenterY-radius+((int)(radius*CIRCLE_LINE_DISTANCE)), Clipper, ReferencingColor); DrawLine(hdc,CenterX,CenterY+((int)(radius*CIRCLE_LINE_DISTANCE)), CenterX,CenterY+radius-((int)(radius*CIRCLE_LINE_DISTANCE)), Clipper,ReferencingColor); }DrawEllipse() zeichnet mir den Kreis und DrawLine() Koordinatenkreuz im Kreis
void CSplitterTestView::DrawEllipse(HDC hdc,int CenterX,int CenterY,int radius,RECT Clipper,COLORREF color) { int steps = CIRLCE_DRAWING_ACCURACY*360 +1; int i; CPen tempcolor(PS_SOLID,1,color); SelectObject(hdc,tempcolor); //Kreispunkteberechnen: for (i=0;i<steps;i++)//TODO:Optimiereung und clipping! { CirclePoints[i].x = round(cos(i/CIRLCE_DRAWING_ACCURACY * (2*PI/360)) * radius + CenterX); CirclePoints[i].y = round(-sin(i/CIRLCE_DRAWING_ACCURACY * (2*PI/360)) * radius + CenterY); } //Kreispunkte verbinden / Kreis zeichen: for (i=0;i<steps-1;i++) { MoveToEx(hdc,CirclePoints[i].x,CirclePoints[i].y,NULL); if(CirclePoints[i+1].x < Clipper.right && CirclePoints[i+1].x > Clipper.left && CirclePoints[i+1].y > Clipper.top && CirclePoints[i+1].y < Clipper.bottom) if(CirclePoints[i].x < Clipper.right && CirclePoints[i].x > Clipper.left && CirclePoints[i].y > Clipper.top && CirclePoints[i].y < Clipper.bottom) LineTo(hdc,CirclePoints[i+1].x,CirclePoints[i+1].y); } }DrawLine werde ich jetzt mal auslassen, geschiet im wesentlichen das gleiche wie im DrawEllipse(). Beim verschieben oder ändern des Kreises geschieht das Problem.
Ich glaube in der Funktion OnMouseMove() wird der Fehler verursacht.void CSplitterTestView::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Code für die Behandlungsroutine für Nachrichten hier einfügen und/oder Standard aufrufen switch(t_SelectedTool) { case NONE: break; case CIRCLE://Mauszeiger über dem Kreis: Cursor switchen: if(!(nFlags==MK_LBUTTON) && !(nFlags==MK_RBUTTON) || RESIZE_MODE || REPOS_MODE!=NONE) { if(PointerInCircle(point) && PointerAtCircleCross(point) == NONE) SetCursor(LoadCursor(NULL, IDC_SIZEALL)); switch (PointerAtCircleBorder(point)) { case TOP: SetCursor(LoadCursor(NULL, IDC_SIZENS)); break; case TOP_RIGHT: SetCursor(LoadCursor(NULL, IDC_SIZENESW)); break; case RIGHT: SetCursor(LoadCursor(NULL, IDC_SIZEWE)); break; case BOTTOM_RIGHT: SetCursor(LoadCursor(NULL, IDC_SIZENWSE)); break; case BOTTOM: SetCursor(LoadCursor(NULL, IDC_SIZENS)); break; case BOTTOM_LEFT: SetCursor(LoadCursor(NULL, IDC_SIZENESW)); break; case LEFT: SetCursor(LoadCursor(NULL, IDC_SIZEWE)); break; case TOP_LEFT: SetCursor(LoadCursor(NULL, IDC_SIZENWSE)); break; } switch(PointerAtCircleCross(point)) { case CIRCLE_CROSS_HORIZONTAL: SetCursor(LoadCursor(NULL, IDC_SIZENS));break; case CIRCLE_CROSS_VERTIKAL: SetCursor(LoadCursor(NULL, IDC_SIZEWE));break; } } //LMB Down im Kreis: Verschieben des Kreises: if(nFlags==MK_LBUTTON && PointerInCircle(point) && !RESIZE_MODE && REPOS_MODE==NONE) { SetCursor(LoadCursor(NULL,IDC_SIZEALL)); //CirclePos = point; CirclePos.x = point.x - PointerOffset.x; CirclePos.y = point.y - PointerOffset.y; GraphObject->SetCirclePos(point.x,point.y,0,TablePos); DrawObject(CIRCLE); Actualize(); } //LMB auf Kreiskreuz: Verschieben in einer Dimension: if(REPOS_MODE!=NONE/*nFlags==MK_LBUTTON && PointerAtCircleCross(point)!=NONE && !RESIZE_MODE*/) { POINT oldpos = GraphObject->GetCirclePosInt(0,TablePos); switch(REPOS_MODE) { case CIRCLE_CROSS_VERTIKAL : CirclePos.x = point.x; CirclePos.y = oldpos.y; GraphObject->SetCirclePos(point.x,oldpos.y,0,TablePos); break; //GraphObject->SetCirclePos(point.x,oldpos.y,0,TablePos);break; case CIRCLE_CROSS_HORIZONTAL: CirclePos.x = oldpos.x; CirclePos.y = point.y; GraphObject->SetCirclePos(oldpos.x,point.y,0,TablePos); break; //CirclePos.x = GraphObject->SetCirclePos(oldpos.x,point.y,0,TablePos);break; case NONE : break; } DrawObject(CIRCLE); Actualize(); } //LMB Down auf dem Kreisrand: Größe / Radius ändern: if(RESIZE_MODE) { //Neuen Radius berechnen: int newRadius = (int)(sqrt(pow(point.x-GraphObject->GetCirclePosInt(0,TablePos).x,2) + pow(point.y-GraphObject->GetCirclePosInt(0,TablePos).y,2))); GraphObject->SetCircleRadius(newRadius,0,TablePos); DrawObject(CIRCLE); Actualize(); } break;so hier muss der Fehler irgendwo liegen.
Gruß wreid
-
Nein! Du verwendest Windows einfach falsch!
Deine Mal-Operationen liegen alle in Deinem Maushandler.
Diese sollten aber in OnDraw stattfinden! Diese zentrale Routine wird immer aufgerufen wenn irgendetwas in Deinem Fenster neu gezeichnet werden muss, weil z.B. ein anderes Fenster, Dein Fenster nicht mehr verdeckt.In OnMouseMove solltest Du nur noch Invalidate aufrufen oder die direkten interaktivem Zeichenoperationen durchführen. Das eigentliche Zeichnen sollte/muss immer in WM_PAINT Handler (OnDraw) stattfinden!
-
Hallo
wenn ich dich richtig verstehe, schlägst du vor, alle Mal-Operationen aus OnDraw zu tätigen. Das heißt, das ich DrawObject nicht mehr benötige, und sein Inhalt in OnDraw stellen kann. Dann verstehe ich nicht wozu man eigentlich CClientDC erzeugen kann um z.B in OnLButtonDown einen Rechteck zu zeichnen.
-
Ja! Alle Mal-Operationen gehören nach OnDraw!
Zum CCLientDC:
Weil es temporäre Mal-Aktionen geben kann, die z.B. nur bei einer Mausaktion stattfinden (Drag&Drop), oder weil gleitende Updates ohne Nachrichtenschleife benötigst, oder WM_PAINT subclassed und an den PaintDC nicht herankommst... Millionen Gründe!
-
Ich bin sehr weit vorgeschritten mit meinem code und kein es nicht mehr so leicht ändern, wird mir nicht so leicht sein es zu ändern. in ondraw habe ich vor einzelne Bilder sowie livebilder auszugeben die ich aus einer Kamera erhalte. deshalb hat ic h vor in einer Funktion drawobject alle anderen mal-Operationen zu tätigen.
ich habe vor in einem bild etwas zu vermessen. kreis-Funktion dient dazu um kreise zu vermessen, später kommt winkel-Funktion dazu, damit kann ich winkel im bild messen. dazu habe ich im Fenster zwei ebenen eingebaut. erste ebene dient für die bilder und die andere ebene für mess Funktionen._____________________________________ | Fenster | | ____________________ | | | Bildebene | | | | _____________|______ | | | | Messebene | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |______|_____________| | | | | | | | |____________________| | | | |_____________________________________|Dieses Bild soll ein wenig deutlich zeigen, was ich vor habe. wenn ich jetzt in der bildebene lade und die kres-funktion lade, erhalte ich bei bewegen des kreises dieses unschönes effekt.
gibts ne funktion die veranlasst das der kreis neu gezeichnet wird, aber die bildeben bestehen bleibt.
-
falls du lust hat mein code anzuschauen, hier ist der link
http://www.informatik.fh-wiesbaden.de/~wreid001/SDraw.rar
freue mich für jede idee
-
Es spielt keine Rolle was Du zeichnest. Dir muss nur klar sein:
Nur wenn Du in OnDraw zeichnest ist garantiert, dass in alen Fällen auch wieder alle Informationen angezeigt werden.Wenn zum Beispiel Dein Fenster minimiert und wieder maximiert wird, dann wird ein WM_PAINT versendet. Du musst nun alles wieder Zeichnen was notwendig ist, und das muss in OnDraw passieren.
Egal welche Layer Du hier vorhast. Das Du hier unterschiedliche Schichten zeichnest ist doch egal. Mach es in OnDraw!
Wenn ein Teil Deines Programmes nun etwas verändert ruft er nur Invalidate aus, was wiederum eine neue WM_PAINT Nachricht versendet und OnDraw sorgt für das Neuzeichnen.