 |
|
|
 |
|
 |
The rectangle flickers. This is very apparent when also filling the rectangle (which I would like to have the option to do). Is there an easy way to avoid/reduce the flickering?
TheMperor
|
|
|
|
 |
|
 |
Thank you for a very nice article.
I need to invert a general polygon shape using the Polygon function.
In Win32 gdi the Polygon function is defined as:
BOOL Polygon(__in HDC hdc,__in const POINT *lpPoints,__in int nCount);
But how do I handle the second parameter from C#?
And do you know a good brief introduction on how to make calls to the Win32 gdi from c#?
|
|
|
|
 |
|
 |
Thank you!
|
|
|
|
 |
|
 |
First let me say that I really like the RubberBand code. I have added the fixes I found in the remarks I've found here and everything seems to working as it should with one exception. The right mouse button down code fails to remove the rectangle. I stepped through the code and the haveRect variable is true causing the Invalidate() code to execute but the rectangle persist. I would appreciate it if someone could tell me where I've gone wrong.
One other thing, all of the PenStyles are working when the Width is 1 but when the Width is increase to 2 or greater only the solid line works. Being new to graphics programming I don't know if this is to be expected. Should I write a condition to handle the PenStyles when they are other than PS_SOLID?
Thanks again for sharing this code and to those who have contributed additional snippets.
|
|
|
|
 |
|
 |
Dear sir ,
I hve Created some controls at runtime & i did moving of single control at runtime but i failed to move multiple controls at runtime . pls can u tell me how to select multiple controls using Control key & how to Drag those at a time .
Thanks,
Lekha.
ChandraLekha
|
|
|
|
 |
|
 |
The .NET pictureBox control exposes two properties: Image and BackgroundImage.
One can set the image one want's to "rubber-band" to the BackgroundImage, and set the Image to a transparent image on which one can draw the rubber band. No need to XOR, just replace the transparent image with a fresh one to erase the prior rectangle.
|
|
|
|
 |
|
|
 |
|
 |
When applying the code to a scrollable panel, the code for MouseUp needs to be modified from
mouseDown = false;
mouseMoving = false;
haveRect = true;
To :
if (e.Button == MouseButtons.Left)
{
mouseDown = false;
mouseMoving = false;
haveRect = true;
}
Without this, when you right click to erase rectangles, then scroll, the last drawn rectangle is redrawn by the Paint code due to the true haveRect value.
Hope this helps someone.
|
|
|
|
 |
|
 |
I want to draw a rubberband rectangle and capture coordinates in a text boxes.For this I used a picture box..and one more problem is i have drawn rubberband lines and captured those values in labels(working fine) but as i have placed scrolling for the from when ever i draw a line and scroll down line gets erased.i am working in VB.NET
can any one help me in solving this problem...
Sowjanya
|
|
|
|
 |
|
 |
I seem to remember just using the graphics.drawrectangle using a 1px width brush with (I think) a cross hatch brush with one transparent color and one white or black color for the rubber band.
Please correct me if this is not the same as what you are looking for.
|
|
|
|
 |
|
 |
yeah, that seems to have produced the same effect for me too with about 10% the hassle
|
|
|
|
 |
|
 |
Are you talking about redrawing the image each time then? This XOR solution is for when it's expensive to redraw the image. I can't see how your cross hatch brush will help with this. Also, DrawReversibleFrame(), which is the recommended route, suffers from some serious problems, especially when activating/deactivating the control, resizing, and moving the window around. This can be made to work with a rubber band rectangle, mostly, but is no good for a cursor line, which is what I need. This solution is the best I've seen, although note that the correction for background works, and is required for solid lines. I've added the fix, added a method for drawing a line instead of a rectangle, and made the class static, below, if this helps anyone. public static class XorGdi { public static int PS_SOLID = 0; public static int PS_DASH = 1; public static int PS_DOT = 2; public static int PS_DASHDOT = 3; public static int PS_DASHDOTDOT = 4; public static void DrawLine(int penStyle, int penWidth, Color col, Graphics grp, int X1, int Y1, int X2, int Y2) { // Extract the Win32 HDC from the Graphics object supplied. IntPtr hdc = grp.GetHdc(); // Create a pen. IntPtr gdiPen = CreatePen(penStyle, penWidth, RGB(col.R, col.G, col.B)); SetROP2(hdc, R2_XORPEN); SetBkMode(hdc, TRANSPARENT); // Set the ROP cdrawint mode to XOR. SetROP2(hdc, R2_XORPEN); // Select the pen into the device context. IntPtr oldPen = SelectObject(hdc, gdiPen); // Draw the line. MoveToEx(hdc, X1, Y1, IntPtr.Zero); LineTo(hdc, X2, Y2); // Put the old stuff back where it was. SelectObject(hdc, oldPen); DeleteObject(gdiPen); // Return the device context to Windows. grp.ReleaseHdc(hdc); } public static void DrawRectangle(int penStyle, int penWidth, Color col, Graphics grp, int X1, int Y1, int X2, int Y2) { // Extract the Win32 HDC from the Graphics object supplied. IntPtr hdc = grp.GetHdc(); // Create a pen. IntPtr gdiPen = CreatePen(penStyle, penWidth, RGB(col.R, col.G, col.B)); SetROP2(hdc, R2_XORPEN); SetBkMode(hdc, TRANSPARENT); // Set the ROP cdrawint mode to XOR. SetROP2( hdc, R2_XORPEN ); // Select the pen into the device context. IntPtr oldPen = SelectObject( hdc, gdiPen ); // Create a stock NULL_BRUSH brush and select it into the device // context so that the rectangle isn't filled. IntPtr oldBrush = SelectObject( hdc, GetStockObject( NULL_BRUSH ) ); // Now XOR the hollow rectangle on the Graphics object with // a dotted outline. Rectangle( hdc, X1, Y1, X2, Y2 ); // Put the old stuff back where it was. SelectObject( hdc, oldBrush ); // no need to delete a stock object SelectObject( hdc, oldPen ); DeleteObject( gdiPen ); // but we do need to delete the pen // Return the device context to Windows. grp.ReleaseHdc( hdc ); } private static int NULL_BRUSH = 5; private static int R2_XORPEN = 7; private static int TRANSPARENT = 1; // C# version of Win32 RGB macro private static int RGB(int R, int G, int B) { return (R | (G << 8) | (B << 16)); } // Use Interop to call the corresponding Win32 GDI functions [System.Runtime.InteropServices.DllImportAttribute( "gdi32.dll" )] private static extern int SetROP2( IntPtr hdc, // Handle to a Win32 device context int enDrawMode // Drawing mode ); [System.Runtime.InteropServices.DllImportAttribute( "gdi32.dll" )] private static extern IntPtr CreatePen( int enPenStyle, int nWidth, // Width of pen int crColor // Color of pen ); [System.Runtime.InteropServices.DllImportAttribute( "gdi32.dll" )] private static extern bool DeleteObject( IntPtr hObject // Win32 GDI handle to object to delete ); [System.Runtime.InteropServices.DllImportAttribute( "gdi32.dll" )] private static extern IntPtr SelectObject( IntPtr hdc, // Win32 GDI device context IntPtr hObject // Win32 GDI handle to object to select ); [System.Runtime.InteropServices.DllImportAttribute( "gdi32.dll" )] private static extern void Rectangle( IntPtr hdc, // Handle to a Win32 device context int X1, // x-coordinate of top left corner int Y1, // y-cordinate of top left corner int X2, // x-coordinate of bottom right corner int Y2 // y-coordinate of bottm right corner ); [System.Runtime.InteropServices.DllImportAttribute( "gdi32.dll" )] private static extern IntPtr GetStockObject( int brStyle // Selected from the WinGDI.h BrushStyles enum ); [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")] private static extern int SetBkMode(IntPtr hdc, int iBkMode); [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")] public static extern void LineTo(IntPtr hdc, int x, int y); [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")] public static extern bool MoveToEx(IntPtr hdc, int x, int y, IntPtr lpPoint); }
|
|
|
|
 |
|
 |
I am wondering is it possible to draw Rubber Band Rectangles on top of WebBrowser Control, which is in the form?
I had a form with web browser control in it. I am thinking about allowing users to draw rectangles on top of browser control.
Appreciate any help.
|
|
|
|
 |
|
 |
Balaji,
I haven't tried it, but I would expect that any object for which you can extract a Graphics object should work as well.
Carl
|
|
|
|
 |
|
 |
How to change background of Rubber Band Rectangle?
For example make it grayscale?
Thanks
|
|
|
|
 |
|
 |
I can't think of a simple way, off hand. You could of course copy out the part of the bitmap within the rectangle, convert it to grayscale, and then copy it back. The rectangle was, after all, originally meant to provide the region of interest for image processing, But I don't know of a simple command, GDI or GDI+.
I looked up ICM as a possible alternative, but that doesn't appear any simpler that what I suggested above.
Carl
|
|
|
|
 |
|
 |
Can you send api sample?
Many,
thanks
|
|
|
|
 |
|
 |
Not sure what you want a sample of. For references on ICM, looking it up on MSDN online is the simplest approach. For converting the region of interest to a grayscale subimage, there is not an API in either GDI or GDI+ that I'm aware of. It's either roll your own with .NET or Win32 or use somebody's library: LeadTools, perhaps, or the Intel Image Processing library.
If you want to do your own, a reasonable starting point is
http://www.codeproject.com/cs/media/csharpgraphicfilters11.asp
"Image Processing for Dummies with C# and GDI+ Part 1 - Per Pixel Filters" By Christian Graus
here in the Code Project. He covers grayscale images in this part. You'll need to use the components of the selection rectangle from the original image and use those to limit the area of the image that gets converted. Note also that he deals with 24 bit images. If you need to work with 32 bit images, do p += 4; instead of p += 3; and the last term in the definition of nOffset is multiplied by 4 rather than 3.
Carl
|
|
|
|
 |
|
 |
Your code defines the following:
private const int NULL_BRUSH = 5;
private const int R2_XORPEN = 7;
private const int BLACK_PEN = 0;
However, in GDI.h (VC7 platform SDK) I see this:
#define WHITE_BRUSH 0
#define LTGRAY_BRUSH 1
#define GRAY_BRUSH 2
#define DKGRAY_BRUSH 3
#define BLACK_BRUSH 4
#define NULL_BRUSH 5
#define HOLLOW_BRUSH NULL_BRUSH
#define WHITE_PEN 6
#define BLACK_PEN 7
#define NULL_PEN 8
Notice that BLACK_PEN is defined the same as WHITE_BRUSH!
I wonder if your code just happens to work because a black pen is typically the default. And because you seem to rely on the background being white to get the XOR effect (if you draw with black in XOR mode, nothing should show up on the screen!)
|
|
|
|
 |
|
 |
Oops, I guess I'm mistaken (although not completely...). You call
IntPtr gdiPen = CreatePen(penStyle, lineWidth, BLACK_PEN);
But what you want here is not the GDI constant BLACK_PEN, but rather the RGB value 0,0,0:
IntPtr gdiPen = CreatePen(penStyle, lineWidth, RGB(0,0,0));
But it doesn't matter in your code because both work out to 0.
|
|
|
|
 |
|
 |
Anyway, I still have a criticism of this code. It draws an XOR rectangle with a black pen, and of course, black is color 0, and if you XOR anything with 0, nothing happens!
The only reason this code works is that it uses a PS_DOT line, which causes part of the line to be drawn with the BACKGROUND color, which is white by default. If you change the line style to PS_SOLID, nothing shows up on the screen!
Instead of
IntPtr gdiPen = CreatePen(penStyle, 1, BLACK_PEN);
SetROP2(hdc, R2_XORPEN);
The code should say
IntPtr gdiPen = CreatePen(penStyle, 1, RGB(255,255,255));
SetROP2(hdc, R2_XORPEN);
SetBkMode(hdc, TRANSPARENT);
And the following definitions need to be added:
[System.Runtime.InteropServices.DllImportAttribute( "gdi32.dll" )]
private static extern int SetBkMode(IntPtr hdc, int iBkMode);
private const int TRANSPARENT = 1;
private const int OPAQUE = 2;
I have tested the above code to verify that it works with both PS_DOT and PS_SOLID.
|
|
|
|
 |
|
 |
David,
Sorry it took so long to get back to you, but I didn't get a notification of your message.
At any rate, I haven't checked your addon, but will take your word for it.
Thanx for the diligent input.
Carl
|
|
|
|
 |
|
|
 |
|
 |
Just a quick observation that I haven't research at all. If I change teh brush type to PS_SOLID there is no output. Any clues?
|
|
|
|
 |