Entwickler-Ecke

Multimedia / Grafik - Panel Autoscroll - Panel Content rendert nicht richtig


Chiyoko - Sa 12.11.16 12:06
Titel: Panel Autoscroll - Panel Content rendert nicht richtig
Hallo liebe Community,

ich habe ein spezielles Problem, was den Renderprozess des Panel-Kontextes angeht.

Problembeschreibung:
Nachdem programmatisch die Autoscrollposition des Panels gesetzt wird, blitzt das Hintergrundbild ganz kurz auf, bleibt dann aber schwarz.
Klicke ich dann mit der Maus in die Map, ist die Position wieder 0,0

Code


Panel

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
public PaintPanel()
{
    DoubleBuffered = true;
    //this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
    //this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
    //this.SetStyle(ControlStyles.UserPaint, true);
    ResizeRedraw = true;
}

public PaintPanel(bool isMap = false)
{
    _isMap = isMap;
    DoubleBuffered = true;
    //this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
    //this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
    //this.SetStyle(ControlStyles.UserPaint, true);
    ResizeRedraw = true;
          
}

protected override void OnPaint(PaintEventArgs e)
{
    if (_isMap)
    {
        if (BackgroundImage != null)
        {
            var destRect = new Rectangle(00, Width, Height);

            e.Graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
            e.Graphics.SmoothingMode = SmoothingMode.HighSpeed;
            e.Graphics.DrawImage(BackgroundImage, destRect, HorizontalScroll.Value, VerticalScroll.Value, Width, Height, GraphicsUnit.Pixel);
            e.Graphics.TranslateTransform(AutoScrollPosition.X, AutoScrollPosition.Y);
        }
    }

    base.OnPaint(e);
}




Autoscroll setzen

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
if(x > (panMap.HorizontalScroll.Maximum - panMap.ClientSize.Width))
    x = (panMap.HorizontalScroll.Maximum - panMap.ClientSize.Width);

if(y > (panMap.VerticalScroll.Maximum - panMap.ClientSize.Height))
    y = (panMap.VerticalScroll.Maximum - panMap.ClientSize.Height);

Application.DoEvents();

Size scrollOffset = new Size(panMap.AutoScrollPosition);
panMap.AutoScrollPosition = new Point((x + scrollOffset.Width), y + scrollOffset.Height);

Point p = panMap.AutoScrollPosition;

panMap.Refresh();
panMap.AutoScrollPosition = p;



Der Panelinhalt besteht aus 4000 Bildern wovon nur Teile gerendert werden, je nachdem, wo sich die Scrollposition befindet.
Wenn Refresh aufgerufen wird, ruft das panMap Panel OnPaint auf und rendert damit den relevanten Teil.


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
if(_mapRenderType == MapRenderType.Worldmap)
{
    e.Graphics.ResetTransform();
    e.Graphics.ScaleTransform(1.0F, 1.0F);
}

Size scrollOffset = new Size(panMap.AutoScrollPosition);
                        
int startX = Math.Min(_worldPicCountX, (e.ClipRectangle.Left - scrollOffset.Width) / _worldPicSize);
int startY = Math.Min(_worldPicCountY, (e.ClipRectangle.Top - scrollOffset.Height) / _worldPicSize);
int endX = Math.Min(_worldPicCountX, (e.ClipRectangle.Right - scrollOffset.Width + _worldPicSize-1) / _worldPicSize);
int endY = Math.Min(_worldPicCountY, (e.ClipRectangle.Bottom - scrollOffset.Height + _worldPicSize-1) / _worldPicSize);
Image imgPic;

for(int x = startX; x < endX; x++)
{
    for(int y = startY; y < endY; y++)
    {
        foreach(var item in Lists.MinimapImagesList)
        {
            if(item.Cx == x && item.Cy == y)
            {
                if(_bmpMatrix[x, y] == null)
                {
                    imgPic = string.IsNullOrEmpty(item.Path) ? _blackBmap : Img.LoadBitmap(item.Path);
                    _bmpMatrix[x, y] = new Bitmap(imgPic, _worldPicSize, _worldPicSize);
                }

                e.Graphics.DrawImage(_bmpMatrix[x, y], new Point(x * _worldPicSize + scrollOffset.Width, y * _worldPicSize + scrollOffset.Height));
            }
        }
    }
}



Beispiel, mit dem das autoscroll funktioniert:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
private void PanMap_MouseMove(object sender, MouseEventArgs e)
{
    if(e.Button == MouseButtons.Left)
    {
        Point changePoint = new Point(e.Location.X - _panMapMousePos.X, e.Location.Y - _panMapMousePos.Y);
        panMap.AutoScrollPosition = new Point(-panMap.AutoScrollPosition.X - changePoint.X, -panMap.AutoScrollPosition.Y - changePoint.Y);
        SetMapSrollValues();
        _panMapMousePos = e.Location;
    }
}

private void SetMapSrollValues()
{
    vScrollbarPanMap.Value = panMap.VerticalScroll.Value;
    hScrollbarPanMap.Value = panMap.HorizontalScroll.Value;
}



Die externe Scrollbar und dessen Code kann gefunden werden:
http://www.codeproject.com/Articles/14801/How-to-skin-scrollbars-for-Panels-in-C


Habt ihr vielleicht einen Tip?


Ralf Jansen - Sa 12.11.16 12:43

Aus den Bruchstücken ist schwer irgendwas, außer vielleicht allgemein Positionen wie Application.DoEvents an der falschen Stelle könnte problematisch sein, abzuleiten. Versuch das Problem in einem kompilierbaren möglichst kleinen Beispiel nachzustellen. Dann schauen wir da gern mal drauf.


Chiyoko - Sa 12.11.16 20:35

Das Problem lag an der Combobox, die ein Usercontrol darstellt.
Klick auf das Panel, auf dem das Usercontrol liegt, rendert alles wie gehabt.

Dann muss ich das Problem auf eine andre weise lösen.