Notifications
Clear all

[Closed] Can DotNet screen cap part of the screen?

Is it possible with DotNet to “screencap” a portion of the screen? I have a dialog that flashes and flickers alot as it redraws itself, and I’d like to take a screencap of the dialog before the redrawing, and use that bitmap to cover up the dialog while it redraws, and then remove the bitmap once the redrawing is done, so it appears to be an instantanous update.

Is it possible with DotNet to capture a portion of the screen?

Thanks!

23 Replies

Well I’m guessing worst case scenario, you could just capture the whole screen and crop the part you want, but it’s not a very clean solution. Is the dialog/control that flashes also .NET? Most of those have some methods to disable redraws while you update them.

I’m totally fine with first grabbing the entire screen, and then cropping down if necessary (although I highly suspect there would be a way to feed the dotnet function a rect so it can target just the area I need)

The dialog is not a DotNet form, it’s a maxscript rollout opened as a dialog, containing a mixture of native maxscript controls and DotNet controls.

Thanks.

Yhea probably, I was just suggestion a possible course of action if you couldn’t make that work.

However I still think you should check all other possibilities first. What about setting the visible property to false on all controls?

I haven’t tried that yet, but I’m pretty sure I’ll still see some flashing… all the controls will disapear for a frame, and then reappear in their new configurations. It’s that flashing that I’m trying to eliminate.

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

the best way to reduce flickering is to disable redraw of whole window before updating of the controls and set to enable after. it’s easy to do. (and much faster then make a screenshot)

Denis,

I’m only aware of disableSceneRedraw() for disabling the redrawing of scenes, and that only seems to affect the 3D world itslef, and not the various UI’s. Is there another command that disables the UI’s from being redrawn as well?

Thanks.

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

it’s how to lock/unlock window redraw:


fn getWinRedrawClass = 
(
 source = ""
 source += "using System;
"
 source += "using System.Runtime.InteropServices;
"
 source += "class WinRedraw 
"
 source += "{
"
 source += "	[DllImport(\"user32.dll\")]
"
 source += "	static extern bool RedrawWindow(IntPtr hWnd, IntPtr lprcUpdate, IntPtr hrgnUpdate, uint flags);
"
 source += "	public bool RedrawAllWindow(IntPtr hWnd, uint flags) { return RedrawWindow(hWnd, IntPtr.Zero, IntPtr.Zero, flags); }
"
 source += "	public bool RedrawAllWindow(Int32 hWnd, uint flags) { return RedrawWindow((IntPtr)hWnd, IntPtr.Zero, IntPtr.Zero, flags); }
"
 source += "}
"
 csharpProvider = dotnetobject "Microsoft.CSharp.CSharpCodeProvider"
 compilerParams = dotnetobject "System.CodeDom.Compiler.CompilerParameters"
 compilerParams.ReferencedAssemblies.Add("System.dll");
 compilerParams.GenerateInMemory = on
 compilerResults = csharpProvider.CompileAssemblyFromSource compilerParams #(source)
 
 input = compilerResults.CompiledAssembly.CreateInstance "WinRedraw"
)
global WinRedrawClass = if WinRedrawClass == undefined then getWinRedrawClass() else WinRedrawClass
try(destroydialog RedrawTestRol) catch()
rollout RedrawTestRol "Redraw Test" width:200 height:240 
(
 fn setWindowRedraw hwnd act = if hwnd != undefined do 
 (
  local WM_SETREDRAW = 0x000B
  windows.sendmessage hwnd WM_SETREDRAW act 1
 )
  
 dotNetControl tv "TreeView" backcolor:(dotNetClass "System.Drawing.Color").Gray width:200 height:200 pos:[0,0]
 button b1 "" width:22 pos:[-100,0]
 button b2 "" width:22 pos:[-100,0]
 button b3 "" width:22 pos:[-100,0]
 button b4 "" width:22 pos:[-100,0]
 button b5 "" width:22 pos:[-100,0]
 
 button lockRedraw "Lock Redraw" width:90 pos:[8, 210]
 button withRedraw "With Redraw" width:90 pos:[100, 210]
 local buttons = #()
 local hwnd
 fn loadTV =
 (
  i = dotnetobject "TreeNode" ""
  items = for k=1 to 400 collect 
  (
   item = i.clone()
   item.text = "Item " + k as string
   item
  )
  tv.BeginUpdate()
  tv.nodes.clear()
  tv.nodes.addrange items
  tv.EndUpdate()
  tv.Refresh()
 )
 
 on lockRedraw pressed do
 (
  setWindowRedraw hwnd 0 -- set redraw to off
  for b in buttons do b.pos = random [0,0] [158,178]
  loadTV()
  setWindowRedraw hwnd 1 -- set redraw to on
  flags = 0x81 -- RDW_INVALIDATE | RDW_ALLCHILDREN
  -- or 
  flags = 0x01 -- RDW_INVALIDATE 
  WinRedrawClass.redrawallwindow hwnd flags -- force redraw
 )
 on withRedraw pressed do
 (
  for b in buttons do b.pos = random [0,0] [158,178]
  loadTV()
 )
 on RedrawTestRol open do
 (
  loadTV()
  hwnd = (windows.getChildHWND 0 "Redraw Test")[1]
  buttons = for b in RedrawTestRol.controls where iskindof b ButtonControl and b.text == "" collect
  (
   b.pos = random [0,0] [158,178]
   b.text = b.name
   b
  )
 )
)
createdialog RedrawTestRol

if anyone knows how to force window redraw without c#, please let me know

 PEN

What exactly are you drawing into? Dotnet objects or Max rollouts and UI items? What you are suggesting would be very slow.

Paul,

Well, right now, when the user hits a certain button causing the dialog to reconfigure itself, I have a big button appear over the entire dialog area to cover up the controls moving to new positions. Once they’re all in place, I move the big button off to -1000,-1000 to reveal the dialog controls again. This of course causes the entire dialog interface to appear blanked out for one frame, but at least keeps the user from seeing individual controls scaling/moving to new locations.

So my thought was, that if I could apply a bitmap to the large button that blocks everything, and that bitmap is just a screenshot of what the dialog looked like before the reconfiguration, it would completely removing the perception of any flashing or anything.

 PEN

Interesting idea. Not sure how to go about that. Does this take a long time?

If you place the controls inside a Panel control, you can use the DrawToBitmap method. You could also have a look at the invalidate and update methods.

Edit: Better yet, try SuspendLayout and ResumeLayout

Page 1 / 3