Skip to main content
gamedev.net
🔒 Locked

application repaint "bug"

Started by gammaGT 6 replies 1.1k views
Original Post
gammaGT
gammaGT
Hi folks, i am creating an application with (possibly) multiple rendertargets and want to render for example to a panel. I wrote a class that manages the device and the controls to render to... My problem is, that the main window's components are not repainted anymore. i tried to override the OnPaint method of the form an invalidate it and its components manually, but no effect... Only when i select an item from the main menu, it's updated once. Does anyone know, what the problem is? thanks!
--I love deadlines. I like the whooshing sound they make as they fly by. (Douglas Adams)
jpetrie
jpetrie
I think you may need to provide more information or word your request better. However, my initial hunch is to suggest that the WM_PAINT message is a "lazy" (i.e., low-priority) message and gets deferred in the pump by other messages. You also only get them when things change (i.e., they are not an "every frame" kind of message). You also may need to be invaldating the window area when you do your own rendering; the paint message probably won't fire automatically for you.
meeshoo
meeshoo
jpetrie is right, you cannot rely only on WM_PAINT. In app for example, when i use paint message i get 99% cpu usage. there, the paint is called to often. so i found the solution: i use the "erase background" message instead. try it yourself, it might work.
gammaGT
gammaGT
ok... sorry, that i didn't post it right away!
I'll try to be more specific.
What i forgot to mention is, that I'm using MDX and C#.
first i tested my stuff in a simple form with nothing in it, except the control i wanted to render to, so i didn't have that problem...
now, i created a windows form, that contains some stuff like textboxes, sliders,
groupboxes and stuff like that, as well as the panel/control i want to render to.
to do this using only one device, i created a kind of manager class that contains the device and the rendercode. the rendertarget is passed to that class before device creation as a control and is stored there.
so far, everything works fine.
rendering itself works fine, also (as it did before)...
but now, all the other controls on the form aren't repainted and i find no workaround.

there's some samplecode:

/// <summary>
/// Constructor for the RenderControlManager
/// </summary>
/// <param name="displayControl"></param>
public RenderControlManager(ref Control displayControl)
{
this.Display = displayControl;
this.CreateDevice();
this.InitializeComponent();
this.InitializeEnvironment();
}

/// <summary>
/// Creates the D3D Device
/// </summary>
private void CreateDevice()
{
if (this.d3dDevice != null)
this.d3dDevice.Dispose();

try
{
PresentParameters presentParams = new PresentParameters();
AdapterInformation adapter = Manager.Adapters.Default;
// setting up a viewport
Viewport vp = new Viewport();
vp.Height = this.Display.Height;
vp.Width = this.Display.Width;
vp.X = this.Display.Location.X;
vp.Y = this.Display.Location.Y;


DisplayMode dm;
if (this.Fullscreen)
{
dm = new DisplayMode();
dm.Width = 640;
dm.Height = 480;
dm.Format = Format.X8R8G8B8;
}
else
dm = adapter.CurrentDisplayMode;

presentParams.SwapEffect = SwapEffect.Copy;
presentParams.BackBufferFormat = Format.Unknown;
if (this.Fullscreen)
{
presentParams.BackBufferFormat = dm.Format;
presentParams.BackBufferWidth = dm.Width;
presentParams.BackBufferHeight = dm.Height;
presentParams.FullScreenRefreshRateInHz = 60;
presentParams.PresentFlag = PresentFlag.None;
presentParams.BackBufferCount = 1;
presentParams.PresentationInterval = PresentInterval.Immediate;
}
presentParams.AutoDepthStencilFormat = DepthFormat.D16;
presentParams.EnableAutoDepthStencil = true;
presentParams.Windowed = !this.Fullscreen;

// Store the default adapter
int adapterOrdinal = Manager.Adapters.Default.Adapter;
CreateFlags flags = CreateFlags.SoftwareVertexProcessing;

// Check to see if we can use a pure hardware device
Caps caps = Manager.GetDeviceCaps(adapterOrdinal, DeviceType.Hardware);

// Do we support hardware vertex processing?
if (caps.DeviceCaps.SupportsHardwareTransformAndLight)
// Replace the software vertex processing
flags = CreateFlags.HardwareVertexProcessing;

// Do we support a pure device?
if (caps.DeviceCaps.SupportsPureDevice)
flags |= CreateFlags.PureDevice;

flags |= CreateFlags.FpuPreserve;

this.d3dDevice = new Device(0, DeviceType.Hardware, this.Display, flags, presentParams);

this.d3dDevice.SamplerState[0].MagFilter = TextureFilter.Linear;
this.d3dDevice.SamplerState[0].MinFilter = TextureFilter.Linear;

this.d3dDevice.DeviceReset += new System.EventHandler(this.OnResetDevice);
this.OnResetDevice(this.d3dDevice, null);

this.projMatrix = Matrix.PerspectiveFovRH((float)Math.PI / 2,
this.Display.Width / this.Display.Height, 1.0f, 30000.0f);

this.d3dDevice.SetTransform(TransformType.Projection, this.projMatrix);

this.worldMatrix = Matrix.Identity;

gridMaterial = new Material();
gridMaterial.Diffuse = Color.White;
gridMaterial.Specular = Color.White;

toolPathMaterial = new Material();
toolPathMaterial.Ambient = Color.Red;
toolPathMaterial.Diffuse = Color.Red;

// Vertexdeklaration



VertexElement[] elements = new VertexElement[]
{
new VertexElement(0, 0, DeclarationType.Float3,
DeclarationMethod.Default, DeclarationUsage.Position, 0),
new VertexElement(0, 12, DeclarationType.Float3,
DeclarationMethod.Default, DeclarationUsage.Normal, 0),
new VertexElement(0, 24, DeclarationType.Color,
DeclarationMethod.Default, DeclarationUsage.Color, 0),
VertexElement.VertexDeclarationEnd
};


this.decl = new VertexDeclaration(this.d3dDevice, elements);

// Set up the Lights
this.setupLights();
this.setupShader();


this.d3dDevice.RenderState.AdaptiveTessellateW = 5f;
this.d3dDevice.RenderState.AdaptiveTessellateX = 5f;
this.d3dDevice.RenderState.AdaptiveTessellateY = 5f;
this.d3dDevice.RenderState.AdaptiveTessellateZ = 5f;
this.d3dDevice.RenderState.MinTessellationLevel = 5f;
this.d3dDevice.RenderState.CullMode = Cull.Clockwise;
this.d3dDevice.RenderState.ShadeMode = ShadeMode.Flat;
this.d3dDevice.RenderState.NormalizeNormals = false;
}
catch (DeviceLostException err)
{
throw new Exception("device lost.", err);
}
catch (DeviceNotResetException err)
{
throw new Exception("device not reset.", err);
}
catch (InvalidCallException err)
{
throw new Exception("Invalid call.", err);
}
catch (NotAvailableException err)
{
throw new Exception("Not available.", err);
}
catch (OutOfVideoMemoryException err)
{
throw new Exception("Out of video memory.", err);
}

}

/// <summary>
/// OnPaint Method
/// </summary>
/// <param name="e">PaintEventArgs</param>
public void OnPaint(PaintEventArgs e)
{

if (this.IsRendering)
{
try
{

//========================= Die Basisfunktion des Controls ausführen

this.d3dDevice.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.LightSteelBlue, 1.0f, 0);

if (this.animControl.Settings.SimulationState == CustomStructs.SimulationState.Running)
{
// get the animated renderList back from the AnimationController
if (!(this.animControl.Settings.TimeState == CustomStructs.TimeState.Freeze))
{
this.animControl.AnimateFrame(DXUtil.Timer(DirectXTimer.GetElapsedTime));
}
else
{
DXUtil.Timer(DirectXTimer.GetElapsedTime);
}
}

UpdateWorld();
this.d3dDevice.BeginScene();

//========================= Die Szene Rendern
this.Render();

this.d3dDevice.EndScene();
this.d3dDevice.Present(this.Display);

//========================= Das Control neu zeichnen
}
catch (Exception err)
{
throw new Exception("Error while rendering", err);
}
}

this.Display.Invalidate();


}
--I love deadlines. I like the whooshing sound they make as they fly by. (Douglas Adams)
jpetrie
jpetrie
So I still see that your actual rendering code is occuring in an OnPaint handler. Normally, that handle will only fire when Windows deems it is neccessary to -- generally relying entirly on a paint message is bad (now, since you do seem to do something that invalidates your window rect inside OnPaint, thus forcing another paint, you are probably getting what you think is correct because your window will get painting the first time its drawn; but this behavior is fragile).

I'm not very familar with C# or MDX, but i looks like maybe your render (the DX stuff) is happening AFTER the windows forms stuff has redrawn its children (eg the controls) and thus your controls get constantly overwritten by your rendering. Maybe try to add some myControl->Draw() or whatever is appropriate calls after you flip your buffer?
gammaGT
gammaGT
thanks, I'll look into that!
--I love deadlines. I like the whooshing sound they make as they fly by. (Douglas Adams)
gammaGT
gammaGT
Ok, that's what i tried:

protected override void WndProc(ref Message m)
{
switch(m.Msg)
{
case 0x000F:
if (rc != null) rc.RenderFrame();
this.OnPaint(new PaintEventArgs(Graphics.FromHwnd(this.Handle), this.ClientRectangle));
break;

default:

base.WndProc(ref m);

break;

}
}

Rendering is smoother now, but the toolbars and stuff like that are
still not redrawn.
I hope i got your suggestion right.
--I love deadlines. I like the whooshing sound they make as they fly by. (Douglas Adams)
gammaGT
gammaGT
ahh... i've finally solved it :)
thanks for the help!
--I love deadlines. I like the whooshing sound they make as they fly by. (Douglas Adams)

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.