By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
455,290 Members | 1,303 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 455,290 IT Pros & Developers. It's quick & easy.

Using The NativeWindow Class To Draw A GDI Type Circle On Top Of A DataGrid Possibly In The Override OnPaint

P: n/a
I have a requirement to put a GDI style circle or rectangle border around
the selected row of a datagrid/ It will overlap into the row above and below
the selected row. Doing this in a the OnPaint of a subclassed
DataGridTextBoxColum dos not seem like a practical way to do it.

I have subclassed a DataGrid and overridden the OnPaint as such:

protected override void OnPaint(PaintEventArgs pe)

{

base.OnPaint(pe);

// Create pen.

Pen blackPen = new Pen(Color.Green, 2);

// Create location and size of rectangle.

float x = 15.0F;

float y = 53.0F;

float width = 500.0F;

float height = 20.0F;

// Draw rectangle to screen.

pe.Graphics.DrawRectangle(blackPen, x, y, width, height);

}

It works but has refresh problems.

Last week Bob Powell [MVP] suggested that I use a NativeWindow class to
solve this problem. I've just had the time to get back to this and not being
a former C++ person, etc., etc., etc. maybe someone can help with this.

The MSDN help screen for the NativeWindow class is this link:

http://msdn.microsoft.com/library/de...classtopic.asp

It has an example and in the subclassed NativeWindow constructor it creates
a button:

public MyNativeWindow(Form parent)

{

...see help example

}

Can someone advise me on where my code above that paints the Rectangle
should go in this NativeWindow example?


Nov 21 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a
Hi,

You should create a datagrid column style to do that. Here is an
example of an image column that shows how to tell when the column is
selected. You will have to draw your circle in the paint event. Keep in
mind that you have to draw part of the circle in each column shown.

Imports System.Drawing

Imports System.Drawing.Drawing2D

Imports System.Windows.Forms

Imports System.Reflection

Imports System.IO

Public Class DataGridImageColumn

Inherits DataGridTextBoxColumn

Dim WithEvents dg As DataGrid

Private arHeights As ArrayList

Private mintOffset As Integer

Private cm As CurrencyManager

Public Sub New()

Me.NullText = "Image not available."

End Sub

Private Sub GetHeightList()

Dim mi As MethodInfo = dg.GetType().GetMethod("get_DataGridRows",
BindingFlags.FlattenHierarchy Or BindingFlags.IgnoreCase Or
BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public Or
BindingFlags.Static)

Dim dgra As Array = CType(mi.Invoke(Me.dg, Nothing), Array)

arHeights = New ArrayList

Dim dgRowHeight As Object

For Each dgRowHeight In dgra

If dgRowHeight.ToString().EndsWith("DataGridRelations hipRow") = True Then

arHeights.Add(dgRowHeight)

End If

Next

End Sub

Protected Overloads Overrides Sub Paint(ByVal g As System.Drawing.Graphics,
ByVal bounds As System.Drawing.Rectangle, ByVal source As
System.Windows.Forms.CurrencyManager, ByVal rowNum As Integer, ByVal
backBrush As System.Drawing.Brush, ByVal foreBrush As System.Drawing.Brush,
ByVal alignToRight As Boolean)

Static bPainted As Boolean = False

Static bMove As Boolean = True

If Not bPainted Then

dg = Me.DataGridTableStyle.DataGrid

cm = source

GetHeightList()

End If

If source.Count - 1 = rowNum And bMove Then

'

' Force resize so scroll bars show

'

dg.Size = New Size(dg.Size.Width, dg.Height - 1)

bMove = False

dg.Size = New Size(dg.Size.Width, dg.Height + 1)

End If

'clear the cell

g.FillRectangle(backBrush, bounds)

Dim objData As Object = Me.GetColumnValueAtRow([source], rowNum)

If TypeOf objData Is System.DBNull Then

Dim sf As New StringFormat

With sf

..Alignment = StringAlignment.Center

..LineAlignment = StringAlignment.Center

End With

g.DrawString(Me.NullText, Me.TextBox.Font, Brushes.Black, _

RectangleF.op_Implicit(bounds), sf)

Else

Try

Dim bm As Bitmap

If TypeOf objData Is String Then

Dim fs As New FileStream(objData.ToString, FileMode.Open)

bm = CType(Bitmap.FromStream(fs), Bitmap)

fs.Close()

Else

Try

bm = ConvertToBitmap(DirectCast(objData, Byte()), 78)

Catch

bm = ConvertToBitmap(DirectCast(objData, Byte()), 0)

End Try

End If

Dim h As Integer

Dim s As Double

s = (Me.Width / bm.Width)

h = CInt(bm.Height * s)

If s >= 1 Then

h = bm.Height

End If

AdjustHeight(h)

Dim r As Rectangle

If Me.Width > bm.Width Then

r = New Rectangle(bounds.Left, bounds.Top, bm.Width, bm.Height)

Else

r = New Rectangle(bounds.Left, bounds.Top, Me.Width, h)

End If

g.DrawImage(bm, r)

If dg.IsSelected(rowNum) Then

Dim br As New SolidBrush(Color.FromArgb(64, _

Me.DataGridTableStyle.SelectionBackColor))

g.FillRectangle(br, bounds)

br.Dispose()

End If

Catch ex As Exception

Dim sf As New StringFormat

With sf

..Alignment = StringAlignment.Center

..LineAlignment = StringAlignment.Center

End With

g.DrawString("Invalid image format", Me.TextBox.Font, Brushes.Black, _

RectangleF.op_Implicit(bounds), sf)

End Try

End If

bPainted = True

End Sub

Protected Overloads Overrides Sub Edit(ByVal source As
System.Windows.Forms.CurrencyManager, ByVal rowNum As Integer, ByVal bounds
As System.Drawing.Rectangle, ByVal [readOnly] As Boolean, ByVal instantText
As String, ByVal cellIsVisible As Boolean)

End Sub

Private Sub AdjustHeight(ByVal h As Integer)

Dim curHeight As Integer = Me.DataGridTableStyle.PreferredRowHeight

If h > curHeight Then

'

' Manually set all the row heights to the new height

'

Me.DataGridTableStyle.PreferredRowHeight = h

Trace.WriteLine(h)

If arHeights.Count < cm.Count Then

GetHeightList()

End If

For rownum As Integer = 0 To cm.Count - 1

Try

Dim pi As PropertyInfo

pi = arHeights(rownum).GetType().GetProperty("Height")

' adjust height

If h > curHeight Then

pi.SetValue(arHeights(rownum), h, Nothing)

End If

Catch

' something wrong leave default height

Debug.WriteLine("Error")

End Try

Next

'

' Resize datagrid to get scrollbars to work right

'

Dim sz As Size = dg.Size

dg.Size = New Size(New Point(sz.Width - 1, sz.Height - 1))

dg.Size = sz

End If

End Sub

Private Function ConvertToBitmap(ByVal data() As Byte, ByVal offset As
Integer) As Bitmap

Dim ms As New System.IO.MemoryStream

Dim bm As Bitmap

ms = New MemoryStream

ms.Write(data, offset, data.Length - offset)

bm = New Bitmap(ms)

Return bm

End Function

<DataSysDescription("Suspends painting of column until EndUpdate is
called")> _

Public Shadows Sub BeginUpdate()

MyBase.BeginUpdate()

End Sub

<DataSysDescription("Resumes painting of column")> _

Public Shadows Sub EndUpdate()

MyBase.EndUpdate()

End Sub

End Class

Ken

---------------------

"Richard" <a@b.com> wrote in message
news:vg********************@twister.nyc.rr.com...
I have a requirement to put a GDI style circle or rectangle border around
the selected row of a datagrid/ It will overlap into the row above and below
the selected row. Doing this in a the OnPaint of a subclassed
DataGridTextBoxColum dos not seem like a practical way to do it.

I have subclassed a DataGrid and overridden the OnPaint as such:

protected override void OnPaint(PaintEventArgs pe)

{

base.OnPaint(pe);

// Create pen.

Pen blackPen = new Pen(Color.Green, 2);

// Create location and size of rectangle.

float x = 15.0F;

float y = 53.0F;

float width = 500.0F;

float height = 20.0F;

// Draw rectangle to screen.

pe.Graphics.DrawRectangle(blackPen, x, y, width, height);

}

It works but has refresh problems.

Last week Bob Powell [MVP] suggested that I use a NativeWindow class to
solve this problem. I've just had the time to get back to this and not being
a former C++ person, etc., etc., etc. maybe someone can help with this.

The MSDN help screen for the NativeWindow class is this link:

http://msdn.microsoft.com/library/de...classtopic.asp

It has an example and in the subclassed NativeWindow constructor it creates
a button:

public MyNativeWindow(Form parent)

{

...see help example

}

Can someone advise me on where my code above that paints the Rectangle
should go in this NativeWindow example?



Nov 21 '05 #2

P: n/a
> Last week Bob Powell [MVP] suggested that I use a NativeWindow class to
solve this problem. I've just had the time to get back to this and not
being
a former C++ person, etc., etc., etc. maybe someone can help with this.
Far be it from me to leave a hint like that hanging in the air ;-)

See after my signature. (lots of lovely interop)

--
Bob Powell [MVP]
Visual C#, System.Drawing

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.

Imports System

Imports System.Drawing

Imports System.Drawing.Drawing2D

Imports System.Collections

Imports System.ComponentModel

Imports System.Windows.Forms

Imports System.Data

Imports System.Runtime.InteropServices

'

' * The example below explains how to use a NativeWindow With the
WS_EX_LAYERED style set to create a window that sits on top of everything.

' * This uses only one window which is mostly transparent. The transparency
is obtained by using some garish color like magenta on the background and
using the SetLayeredWindowAttributes API to create the transparency key.

' *

' * The window draws on top of everything including the desktop but is a
true window so better managed than raw desktop drawing.

' *

'

Namespace LayeredWindowTest

'/ <summary>

'/ Summary description for Form1.

'/ </summary>
Public Class Form1

Inherits System.Windows.Forms.Form

Private WithEvents timer1 As System.Windows.Forms.Timer

Private button1 As System.Windows.Forms.Button

Private textBox1 As System.Windows.Forms.TextBox

Private listBox1 As System.Windows.Forms.ListBox

Private components As System.ComponentModel.IContainer

Public Sub New()

'

' Required for Windows Form Designer suppoTest

'

InitializeComponent()

End Sub 'New
'

' TODO: Add any constructor code after InitializeComponent call

'
'/ <summary>

'/ Clean up any resources being used.

'/ </summary>

Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)

If disposing Then

If Not (components Is Nothing) Then

components.Dispose()

End If

End If

MyBase.Dispose(disposing)

End Sub 'Dispose

#Region "Windows Form Designer generated code"

'/ <summary>

'/ Required method for Designer suppoTest - do not modify

'/ the contents of this method with the code editor.

'/ </summary>

Private Sub InitializeComponent()

Me.components = New System.ComponentModel.Container

Me.timer1 = New System.Windows.Forms.Timer(Me.components)

Me.button1 = New System.Windows.Forms.Button

Me.textBox1 = New System.Windows.Forms.TextBox

Me.listBox1 = New System.Windows.Forms.ListBox

Me.SuspendLayout()

'

' timer1

'

Me.timer1.Enabled = True

Me.timer1.Interval = 50

'

' button1

'

Me.button1.Location = New System.Drawing.Point(56, 48)

Me.button1.Name = "button1"

Me.button1.TabIndex = 0

Me.button1.Text = "button1"

'

' textBox1

'

Me.textBox1.Location = New System.Drawing.Point(168, 144)

Me.textBox1.Name = "textBox1"

Me.textBox1.TabIndex = 1

Me.textBox1.Text = "textBox1"

'

' listBox1

'

Me.listBox1.Location = New System.Drawing.Point(24, 88)

Me.listBox1.Name = "listBox1"

Me.listBox1.Size = New System.Drawing.Size(120, 95)

Me.listBox1.TabIndex = 2

'

' Form1

'

Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)

Me.ClientSize = New System.Drawing.Size(292, 273)

Me.Controls.Add(listBox1)

Me.Controls.Add(textBox1)

Me.Controls.Add(button1)

Me.Name = "Form1"

Me.Text = "Form1"

Me.ResumeLayout(False)

End Sub 'InitializeComponent

#End Region

'/ <summary>

'/ The main entry point for the application.

'/ </summary>

<STAThread()> _

Shared Sub Main()

Application.Run(New Form1)

End Sub 'Main

Private x As Integer = 30

Private y As Integer = 30

Private dir As Integer = 1

Private Sub timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs)
Handles timer1.Tick

x += dir

y += dir

If x > Me.Width - 30 OrElse x < 30 Then

dir = -dir

End If

lwt.Location = New Point(10, 10)

lwt.Size = New Size(x, y)

End Sub 'timer1_Tick

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Handles MyBase.Load

lwt.Create(Me)

lwt.Show()

End Sub 'Form1_Load

Private lwt As New LayeredWindowTest

End Class 'Form1


Class LayeredWindowTest

Inherits NativeWindow

<DllImport("User32.dll")> _

Public Shared Function MoveWindow(ByVal hWnd As IntPtr, ByVal X As Integer,
ByVal Y As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal
bRepaint As Integer) As Integer

End Function

<DllImport("User32.dll")> _

Public Shared Function ShowWindow(ByVal hWnd As System.IntPtr, ByVal cmdShow
As Short) As Integer

End Function

<DllImport("User32.dll")> _

Public Shared Function BeginPaint(ByVal p As IntPtr, ByRef ps As
PAINTSTRUCT) As IntPtr

End Function

<DllImport("User32.dll")> _

Public Shared Function EndPaint(ByVal p As IntPtr, ByRef ps As PAINTSTRUCT)
As Integer

End Function

<DllImport("User32.dll")> _

Public Shared Function SetLayeredWindowAttributes(ByVal hWnd As IntPtr,
ByVal clrKey As COLORREF, ByVal bAlpha As Byte, ByVal dwFlags As Integer) As
Integer

End Function

Private _internalLocation As POINT

Private _location As POINT

Public Property Location() As POINT

Get

Return _location

End Get

Set(ByVal Value As POINT)

_location = Value

Dim tp As New Point(Value.X, Value.Y)

tp = _parent.PointToScreen(tp)

_internalLocation.X = tp.X

_internalLocation.Y = tp.Y

If Not Me.Handle.Equals(IntPtr.Zero) Then

MoveWindow(Me.Handle, _internalLocation.X, _internalLocation.Y, _size.Width,
_size.Height, 1)

End If

End Set

End Property

Private _size As Size

Public Property Size() As Size

Get

Return _size

End Get

Set(ByVal Value As Size)

_size = Value

If Not Me.Handle.Equals(IntPtr.Zero) Then

MoveWindow(Me.Handle, _internalLocation.X, _internalLocation.Y, _size.Width,
_size.Height, 1)

End If

End Set

End Property

Private _parent As Control

Public Sub Create(ByVal parent As Control)

Me._parent = parent

Dim cp As New CreateParams

cp.Style = CInt(WSDefs.WS_POPUP)

cp.ClassStyle = CInt(CSDefs.CS_OWNDC)

cp.ExStyle = cp.ExStyle Or (CInt(WSDefs.WS_EX_LAYERED) Or
CInt(WSDefs.WS_EX_TOPMOST))

cp.ClassName = Nothing

cp.Caption = Nothing

cp.X = -2

cp.Y = -2

cp.Width = 1

cp.Height = 1

cp.Parent = parent.Handle

CreateHandle(cp)

End Sub 'Create

Protected Overrides Sub WndProc(ByRef m As Message)

Select Case m.Msg

Case CInt(WMDefs.WM_PAINT)

Dim g As Graphics

Dim ps As New PAINTSTRUCT

g = Graphics.FromHdc(BeginPaint(m.HWnd, ps))

g.SmoothingMode = SmoothingMode.None

g.Clear(Color.Magenta)

Dim clipRect As Rectangle = Me._parent.ClientRectangle

clipRect.Offset(-Me.Location.X, -Me.Location.Y)

Dim p As New Pen(Color.Red, 3)

g.SmoothingMode = SmoothingMode.AntiAlias

g.DrawEllipse(p, 2, 2, Me.Size.Width - 4, Me.Size.Height - 4)

p.Dispose()

g.Dispose()

EndPaint(m.HWnd, ps)

m.Result = New IntPtr(0)

Case Else

MyBase.WndProc(m)

End Select

End Sub 'WndProc

Public Sub Show()

If Not Me.Handle.Equals(IntPtr.Zero) Then

ShowWindow(Me.Handle, CShort(SWDefs.SW_SHOWNOACTIVATE))

Dim cr As New COLORREF

cr.Color = Color.Magenta

SetLayeredWindowAttributes(Me.Handle, cr, 0, CInt(LWADefs.LWA_COLORKEY))

End If

End Sub 'Show

End Class 'LayeredWindowTest

Public Enum WMDefs

WM_NULL = &H0

WM_CREATE = &H1

WM_DESTROY = &H2

WM_MOVE = &H3

WM_SIZE = &H5

WM_ACTIVATE = &H6

WA_INACTIVE = 0

WA_ACTIVE = 1

WA_CLICKACTIVE = 2

WM_SETFOCUS = &H7

WM_KILLFOCUS = &H8

WM_ENABLE = &HA

WM_SETREDRAW = &HB

WM_SETTEXT = &HC

WM_GETTEXT = &HD

WM_GETTEXTLENGTH = &HE

WM_PAINT = &HF

WM_CLOSE = &H10

WM_QUERYENDSESSION = &H11

WM_QUERYOPEN = &H13

WM_ENDSESSION = &H16

WM_QUIT = &H12

WM_ERASEBKGND = &H14

WM_SYSCOLORCHANGE = &H15

WM_SHOWWINDOW = &H18

WM_WININICHANGE = &H1A

WM_SETTINGCHANGE = WM_WININICHANGE

WM_DEVMODECHANGE = &H1B

WM_ACTIVATEAPP = &H1C

WM_FONTCHANGE = &H1D

WM_TIMECHANGE = &H1E

WM_CANCELMODE = &H1F

WM_SETCURSOR = &H20

WM_MOUSEACTIVATE = &H21

WM_CHILDACTIVATE = &H22

WM_QUEUESYNC = &H23

WM_GETMINMAXINFO = &H24

WM_PAINTICON = &H26

WM_ICONERASEBKGND = &H27

WM_NEXTDLGCTL = &H28

WM_SPOOLERSTATUS = &H2A

WM_DRAWITEM = &H2B

WM_MEASUREITEM = &H2C

WM_DELETEITEM = &H2D

WM_VKEYTOITEM = &H2E

WM_CHARTOITEM = &H2F

WM_SETFONT = &H30

WM_GETFONT = &H31

WM_SETHOTKEY = &H32

WM_GETHOTKEY = &H33

WM_QUERYDRAGICON = &H37

WM_COMPAREITEM = &H39

WM_GETOBJECT = &H3D

WM_COMPACTING = &H41

WM_COMMNOTIFY = &H44

WM_WINDOWPOSCHANGING = &H46

WM_WINDOWPOSCHANGED = &H47

WM_POWER = &H48

PWR_OK = 1

PWR_FAIL = &HFFFF

PWR_SUSPENDREQUEST = 1

PWR_SUSPENDRESUME = 2

PWR_CRITICALRESUME = 3

WM_COPYDATA = &H4A

WM_CANCELJOURNAL = &H4B

WM_NOTIFY = &H4E

WM_INPUTLANGCHANGEREQUEST = &H50

WM_INPUTLANGCHANGE = &H51

WM_TCARD = &H52

WM_HELP = &H53

WM_USERCHANGED = &H54

WM_NOTIFYFORMAT = &H55

NFR_ANSI = 1

NFR_UNICODE = 2

NF_QUERY = 3

NF_REQUERY = 4

WM_CONTEXTMENU = &H7B

WM_STYLECHANGING = &H7C

WM_STYLECHANGED = &H7D

WM_DISPLAYCHANGE = &H7E

WM_GETICON = &H7F

WM_SETICON = &H80

WM_NCCREATE = &H81

WM_NCDESTROY = &H82

WM_NCCALCSIZE = &H83

WM_NCHITTEST = &H84

WM_NCPAINT = &H85

WM_NCACTIVATE = &H86

WM_GETDLGCODE = &H87

WM_SYNCPAINT = &H88

WM_NCMOUSEMOVE = &HA0

WM_NCLBUTTONDOWN = &HA1

WM_NCLBUTTONUP = &HA2

WM_NCLBUTTONDBLCLK = &HA3

WM_NCRBUTTONDOWN = &HA4

WM_NCRBUTTONUP = &HA5

WM_NCRBUTTONDBLCLK = &HA6

WM_NCMBUTTONDOWN = &HA7

WM_NCMBUTTONUP = &HA8

WM_NCMBUTTONDBLCLK = &HA9

WM_NCXBUTTONDOWN = &HAB

WM_NCXBUTTONUP = &HAC

WM_NCXBUTTONDBLCLK = &HAD

WM_INPUT = &HFF

WM_KEYFIRST = &H100

WM_KEYDOWN = &H100

WM_KEYUP = &H101

WM_CHAR = &H102

WM_DEADCHAR = &H103

WM_SYSKEYDOWN = &H104

WM_SYSKEYUP = &H105

WM_SYSCHAR = &H106

WM_SYSDEADCHAR = &H107

WM_UNICHAR = &H109

WM_KEYLAST = &H108

UNICODE_NOCHAR = &HFFFF

WM_IME_STARTCOMPOSITION = &H10D

WM_IME_ENDCOMPOSITION = &H10E

WM_IME_COMPOSITION = &H10F

WM_IME_KEYLAST = &H10F

WM_INITDIALOG = &H110

WM_COMMAND = &H111

WM_SYSCOMMAND = &H112

WM_TIMER = &H113

WM_HSCROLL = &H114

WM_VSCROLL = &H115

WM_INITMENU = &H116

WM_INITMENUPOPUP = &H117

WM_MENUSELECT = &H11F

WM_MENUCHAR = &H120

WM_ENTERIDLE = &H121

WM_MENURBUTTONUP = &H122

WM_MENUDRAG = &H123

WM_MENUGETOBJECT = &H124

WM_UNINITMENUPOPUP = &H125

WM_MENUCOMMAND = &H126

WM_CHANGEUISTATE = &H127

WM_UPDATEUISTATE = &H128

WM_QUERYUISTATE = &H129

UIS_SET = 1

UIS_CLEAR = 2

UIS_INITIALIZE = 3

UISF_HIDEFOCUS = &H1

UISF_HIDEACCEL = &H2

UISF_ACTIVE = &H4

WM_CTLCOLOR = &H19

WM_CTLCOLORMSGBOX = &H132

WM_CTLCOLOREDIT = &H133

WM_CTLCOLORLISTBOX = &H134

WM_CTLCOLORBTN = &H135

WM_CTLCOLORDLG = &H136

WM_CTLCOLORSCROLLBAR = &H137

WM_CTLCOLORSTATIC = &H138

MN_GETHMENU = &H1E1

WM_MOUSEFIRST = &H200

WM_MOUSEMOVE = &H200

WM_LBUTTONDOWN = &H201

WM_LBUTTONUP = &H202

WM_LBUTTONDBLCLK = &H203

WM_RBUTTONDOWN = &H204

WM_RBUTTONUP = &H205

WM_RBUTTONDBLCLK = &H206

WM_MBUTTONDOWN = &H207

WM_MBUTTONUP = &H208

WM_MBUTTONDBLCLK = &H209

WM_MOUSEWHEEL = &H20A

WM_XBUTTONDOWN = &H20B

WM_XBUTTONUP = &H20C

WM_XBUTTONDBLCLK = &H20D

WM_MOUSELAST = &H20D

WHEEL_DELTA = 120

XBUTTON1 = &H1

XBUTTON2 = &H2

WM_PARENTNOTIFY = &H210

WM_ENTERMENULOOP = &H211

WM_EXITMENULOOP = &H212

WM_NEXTMENU = &H213

WM_SIZING = &H214

WM_CAPTURECHANGED = &H215

WM_MOVING = &H216

WM_POWERBROADCAST = &H218

PBT_APMQUERYSUSPEND = &H0

PBT_APMQUERYSTANDBY = &H1

PBT_APMQUERYSUSPENDFAILED = &H2

PBT_APMQUERYSTANDBYFAILED = &H3

PBT_APMSUSPEND = &H4

PBT_APMSTANDBY = &H5

PBT_APMRESUMECRITICAL = &H6

PBT_APMRESUMESUSPEND = &H7

PBT_APMRESUMESTANDBY = &H8

PBTF_APMRESUMEFROMFAILURE = &H1

PBT_APMBATTERYLOW = &H9

PBT_APMPOWERSTATUSCHANGE = &HA

PBT_APMOEMEVENT = &HB

PBT_APMRESUMEAUTOMATIC = &H12

WM_DEVICECHANGE = &H219

WM_MDICREATE = &H220

WM_MDIDESTROY = &H221

WM_MDIACTIVATE = &H222

WM_MDIRESTORE = &H223

WM_MDINEXT = &H224

WM_MDIMAXIMIZE = &H225

WM_MDITILE = &H226

WM_MDICASCADE = &H227

WM_MDIICONARRANGE = &H228

WM_MDIGETACTIVE = &H229

WM_MDISETMENU = &H230

WM_ENTERSIZEMOVE = &H231

WM_EXITSIZEMOVE = &H232

WM_DROPFILES = &H233

WM_MDIREFRESHMENU = &H234

WM_IME_SETCONTEXT = &H281

WM_IME_NOTIFY = &H282

WM_IME_CONTROL = &H283

WM_IME_COMPOSITIONFULL = &H284

WM_IME_SELECT = &H285

WM_IME_CHAR = &H286

WM_IME_REQUEST = &H288

WM_IME_KEYDOWN = &H290

WM_IME_KEYUP = &H291

WM_MOUSEHOVER = &H2A1

WM_MOUSELEAVE = &H2A3

WM_NCMOUSELEAVE = &H2A2

WM_WTSSESSION_CHANGE = &H2B1

WM_TABLET_FIRST = &H2C0

WM_TABLET_LAST = &H2DF

WM_CUT = &H300

WM_COPY = &H301

WM_PASTE = &H302

WM_CLEAR = &H303

WM_UNDO = &H304

WM_RENDERFORMAT = &H305

WM_RENDERALLFORMATS = &H306

WM_DESTROYCLIPBOARD = &H307

WM_DRAWCLIPBOARD = &H308

WM_PAINTCLIPBOARD = &H309

WM_VSCROLLCLIPBOARD = &H30A

WM_SIZECLIPBOARD = &H30B

WM_ASKCBFORMATNAME = &H30C

WM_CHANGECBCHAIN = &H30D

WM_HSCROLLCLIPBOARD = &H30E

WM_QUERYNEWPALETTE = &H30F

WM_PALETTEISCHANGING = &H310

WM_PALETTECHANGED = &H311

WM_HOTKEY = &H312

WM_PRINT = &H317

WM_PRINTCLIENT = &H318

WM_APPCOMMAND = &H319

WM_THEMECHANGED = &H31A

WM_HANDHELDFIRST = &H358

WM_HANDHELDLAST = &H35F

WM_AFXFIRST = &H360

WM_AFXLAST = &H37F

WM_PENWINFIRST = &H380

WM_PENWINLAST = &H38F

WM_USER = &H400

WM_REFLECT = &H2000

WM_APP = &H8000

End Enum 'WMDefs

Public Enum CSDefs

CS_VREDRAW = &H1

CS_HREDRAW = &H2

CS_DBLCLKS = &H8

CS_OWNDC = &H20

CS_CLASSDC = &H40

CS_PARENTDC = &H80

CS_NOCLOSE = &H200

CS_SAVEBITS = &H800

CS_BYTEALIGNCLIENT = &H1000

CS_BYTEALIGNWINDOW = &H2000

CS_GLOBALCLASS = &H4000

CS_IME = &H10000

CS_DROPSHADOW = &H20000

End Enum 'CSDefs

Public Enum LWADefs

LWA_COLORKEY = &H1

LWA_ALPHA = &H2

End Enum 'LWADefs

<Flags()> _

Public Enum SWDefs

SW_HIDE = 0

SW_SHOWNORMAL = 1

SW_NORMAL = 1

SW_SHOWMINIMIZED = 2

SW_SHOWMAXIMIZED = 3

SW_MAXIMIZE = 3

SW_SHOWNOACTIVATE = 4

SW_SHOW = 5

SW_MINIMIZE = 6

SW_SHOWMINNOACTIVE = 7

SW_SHOWNA = 8

SW_RESTORE = 9

SW_SHOWDEFAULT = 10

SW_FORCEMINIMIZE = 11

SW_MAX = 11

End Enum 'SWDefs

Public Enum WSDefs

WS_OVERLAPPED = &H0

WS_POPUP = &H80000000

WS_CHILD = &H40000000

WS_MINIMIZE = &H20000000

WS_VISIBLE = &H10000000

WS_DISABLED = &H8000000

WS_CLIPSIBLINGS = &H4000000

WS_CLIPCHILDREN = &H2000000

WS_MAXIMIZE = &H1000000

WS_CAPTION = &HC00000 ' WS_BORDER or WS_DLGFRAME

WS_BORDER = &H800000

WS_DLGFRAME = &H400000

WS_VSCROLL = &H200000

WS_HSCROLL = &H100000

WS_SYSMENU = &H80000

WS_THICKFRAME = &H40000

WS_GROUP = &H20000

WS_TABSTOP = &H10000

WS_MINIMIZEBOX = &H20000

WS_MAXIMIZEBOX = &H10000

WS_TILED = WS_OVERLAPPED

WS_ICONIC = WS_MINIMIZE

WS_SIZEBOX = WS_THICKFRAME

WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW

'

' * Common Window Styles

'

WS_OVERLAPPEDWINDOW = (WS_OVERLAPPED Or _

WS_CAPTION Or _

WS_SYSMENU Or _

WS_THICKFRAME Or _

WS_MINIMIZEBOX Or _

WS_MAXIMIZEBOX)

WS_POPUPWINDOW = (WS_POPUP Or _

WS_BORDER Or _

WS_SYSMENU)

WS_CHILDWINDOW = WS_CHILD

'

' * Extended Window Styles

'

WS_EX_DLGMODALFRAME = &H1

WS_EX_NOPARENTNOTIFY = &H4

WS_EX_TOPMOST = &H8

WS_EX_ACCEPTFILES = &H10

WS_EX_TRANSPARENT = &H20

WS_EX_MDICHILD = &H40

WS_EX_TOOLWINDOW = &H80

WS_EX_WINDOWEDGE = &H100

WS_EX_CLIENTEDGE = &H200

WS_EX_CONTEXTHELP = &H400

WS_EX_RIGHT = &H1000

WS_EX_LEFT = &H0

WS_EX_RTLREADING = &H2000

WS_EX_LTRREADING = &H0

WS_EX_LEFTSCROLLBAR = &H4000

WS_EX_RIGHTSCROLLBAR = &H0

WS_EX_CONTROLPARENT = &H10000

WS_EX_STATICEDGE = &H20000

WS_EX_APPWINDOW = &H40000

WS_EX_OVERLAPPEDWINDOW = (WS_EX_WINDOWEDGE Or WS_EX_CLIENTEDGE)

WS_EX_PALETTEWINDOW = (WS_EX_WINDOWEDGE Or WS_EX_TOOLWINDOW Or
WS_EX_TOPMOST)

WS_EX_LAYERED = &H80000

WS_EX_NOINHERITLAYOUT = &H100000 ' Disable inheritence of mirroring by
children

WS_EX_LAYOUTRTL = &H400000 ' Right to left mirroring

WS_EX_COMPOSITED = &H2000000

WS_EX_NOACTIVATE = &H8000000

End Enum 'WSDefs

Public Structure COLORREF

Public _color As Integer

Public Property Color() As Color

Get

Return ColorTranslator.FromWin32(_color)

End Get

Set(ByVal Value As Color)

_color = ColorTranslator.ToWin32(Value)

End Set

End Property

End Structure 'COLORREF

Public Structure PAINTSTRUCT

Public hdc As IntPtr

Public fErase As Integer

Public rcPaint As RECT

Public fRestore As Integer

Public fIncUpdate As Integer

Public rgbReserved1 As Long

Public rgbReserved2 As Long

Public rgbReserved3 As Long

Public rgbReserved4 As Long

End Structure 'PAINTSTRUCT

<StructLayout(LayoutKind.Sequential)> _

Public Structure RECT

Public left As Integer

Public top As Integer

Public right As Integer

Public bottom As Integer

Public ReadOnly Property Width() As Integer

Get

Return right - left

End Get

End Property

Public ReadOnly Property Height() As Integer

Get

Return bottom - top

End Get

End Property

End Structure 'RECT

End Namespace 'LayeredWindowTest


"Richard" <a@b.com> wrote in message
news:vg********************@twister.nyc.rr.com...I have a requirement to put a GDI style circle or rectangle border around
the selected row of a datagrid/ It will overlap into the row above and
below
the selected row. Doing this in a the OnPaint of a subclassed
DataGridTextBoxColum dos not seem like a practical way to do it.

I have subclassed a DataGrid and overridden the OnPaint as such:

protected override void OnPaint(PaintEventArgs pe)

{

base.OnPaint(pe);

// Create pen.

Pen blackPen = new Pen(Color.Green, 2);

// Create location and size of rectangle.

float x = 15.0F;

float y = 53.0F;

float width = 500.0F;

float height = 20.0F;

// Draw rectangle to screen.

pe.Graphics.DrawRectangle(blackPen, x, y, width, height);

}

It works but has refresh problems.

Last week Bob Powell [MVP] suggested that I use a NativeWindow class to
solve this problem. I've just had the time to get back to this and not
being
a former C++ person, etc., etc., etc. maybe someone can help with this.

The MSDN help screen for the NativeWindow class is this link:

http://msdn.microsoft.com/library/de...classtopic.asp

It has an example and in the subclassed NativeWindow constructor it
creates
a button:

public MyNativeWindow(Form parent)

{

..see help example

}

Can someone advise me on where my code above that paints the Rectangle
should go in this NativeWindow example?


Nov 21 '05 #3

P: n/a
Hello

Yes, this is the approach I was trying to avoid. How would your method/code
work if it was the top row of the DataGrid. How would you suggest making the
part of the circle that will have to go over the column headings or in fact
even the title bar?

Thank you,

Richard
"Ken Tucker [MVP]" <vb***@bellsouth.net> wrote in message
news:O0**************@TK2MSFTNGP10.phx.gbl...
Hi,

You should create a datagrid column style to do that. Here is an
example of an image column that shows how to tell when the column is
selected. You will have to draw your circle in the paint event. Keep in
mind that you have to draw part of the circle in each column shown.

Imports System.Drawing

Imports System.Drawing.Drawing2D

Imports System.Windows.Forms

Imports System.Reflection

Imports System.IO

Public Class DataGridImageColumn

Inherits DataGridTextBoxColumn

Dim WithEvents dg As DataGrid

Private arHeights As ArrayList

Private mintOffset As Integer

Private cm As CurrencyManager

Public Sub New()

Me.NullText = "Image not available."

End Sub

Private Sub GetHeightList()

Dim mi As MethodInfo = dg.GetType().GetMethod("get_DataGridRows",
BindingFlags.FlattenHierarchy Or BindingFlags.IgnoreCase Or
BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public Or
BindingFlags.Static)

Dim dgra As Array = CType(mi.Invoke(Me.dg, Nothing), Array)

arHeights = New ArrayList

Dim dgRowHeight As Object

For Each dgRowHeight In dgra

If dgRowHeight.ToString().EndsWith("DataGridRelations hipRow") = True Then

arHeights.Add(dgRowHeight)

End If

Next

End Sub

Protected Overloads Overrides Sub Paint(ByVal g As System.Drawing.Graphics, ByVal bounds As System.Drawing.Rectangle, ByVal source As
System.Windows.Forms.CurrencyManager, ByVal rowNum As Integer, ByVal
backBrush As System.Drawing.Brush, ByVal foreBrush As System.Drawing.Brush, ByVal alignToRight As Boolean)

Static bPainted As Boolean = False

Static bMove As Boolean = True

If Not bPainted Then

dg = Me.DataGridTableStyle.DataGrid

cm = source

GetHeightList()

End If

If source.Count - 1 = rowNum And bMove Then

'

' Force resize so scroll bars show

'

dg.Size = New Size(dg.Size.Width, dg.Height - 1)

bMove = False

dg.Size = New Size(dg.Size.Width, dg.Height + 1)

End If

'clear the cell

g.FillRectangle(backBrush, bounds)

Dim objData As Object = Me.GetColumnValueAtRow([source], rowNum)

If TypeOf objData Is System.DBNull Then

Dim sf As New StringFormat

With sf

.Alignment = StringAlignment.Center

.LineAlignment = StringAlignment.Center

End With

g.DrawString(Me.NullText, Me.TextBox.Font, Brushes.Black, _

RectangleF.op_Implicit(bounds), sf)

Else

Try

Dim bm As Bitmap

If TypeOf objData Is String Then

Dim fs As New FileStream(objData.ToString, FileMode.Open)

bm = CType(Bitmap.FromStream(fs), Bitmap)

fs.Close()

Else

Try

bm = ConvertToBitmap(DirectCast(objData, Byte()), 78)

Catch

bm = ConvertToBitmap(DirectCast(objData, Byte()), 0)

End Try

End If

Dim h As Integer

Dim s As Double

s = (Me.Width / bm.Width)

h = CInt(bm.Height * s)

If s >= 1 Then

h = bm.Height

End If

AdjustHeight(h)

Dim r As Rectangle

If Me.Width > bm.Width Then

r = New Rectangle(bounds.Left, bounds.Top, bm.Width, bm.Height)

Else

r = New Rectangle(bounds.Left, bounds.Top, Me.Width, h)

End If

g.DrawImage(bm, r)

If dg.IsSelected(rowNum) Then

Dim br As New SolidBrush(Color.FromArgb(64, _

Me.DataGridTableStyle.SelectionBackColor))

g.FillRectangle(br, bounds)

br.Dispose()

End If

Catch ex As Exception

Dim sf As New StringFormat

With sf

.Alignment = StringAlignment.Center

.LineAlignment = StringAlignment.Center

End With

g.DrawString("Invalid image format", Me.TextBox.Font, Brushes.Black, _

RectangleF.op_Implicit(bounds), sf)

End Try

End If

bPainted = True

End Sub

Protected Overloads Overrides Sub Edit(ByVal source As
System.Windows.Forms.CurrencyManager, ByVal rowNum As Integer, ByVal bounds As System.Drawing.Rectangle, ByVal [readOnly] As Boolean, ByVal instantText As String, ByVal cellIsVisible As Boolean)

End Sub

Private Sub AdjustHeight(ByVal h As Integer)

Dim curHeight As Integer = Me.DataGridTableStyle.PreferredRowHeight

If h > curHeight Then

'

' Manually set all the row heights to the new height

'

Me.DataGridTableStyle.PreferredRowHeight = h

Trace.WriteLine(h)

If arHeights.Count < cm.Count Then

GetHeightList()

End If

For rownum As Integer = 0 To cm.Count - 1

Try

Dim pi As PropertyInfo

pi = arHeights(rownum).GetType().GetProperty("Height")

' adjust height

If h > curHeight Then

pi.SetValue(arHeights(rownum), h, Nothing)

End If

Catch

' something wrong leave default height

Debug.WriteLine("Error")

End Try

Next

'

' Resize datagrid to get scrollbars to work right

'

Dim sz As Size = dg.Size

dg.Size = New Size(New Point(sz.Width - 1, sz.Height - 1))

dg.Size = sz

End If

End Sub

Private Function ConvertToBitmap(ByVal data() As Byte, ByVal offset As
Integer) As Bitmap

Dim ms As New System.IO.MemoryStream

Dim bm As Bitmap

ms = New MemoryStream

ms.Write(data, offset, data.Length - offset)

bm = New Bitmap(ms)

Return bm

End Function

<DataSysDescription("Suspends painting of column until EndUpdate is
called")> _

Public Shadows Sub BeginUpdate()

MyBase.BeginUpdate()

End Sub

<DataSysDescription("Resumes painting of column")> _

Public Shadows Sub EndUpdate()

MyBase.EndUpdate()

End Sub

End Class

Ken

---------------------

"Richard" <a@b.com> wrote in message
news:vg********************@twister.nyc.rr.com...
I have a requirement to put a GDI style circle or rectangle border around
the selected row of a datagrid/ It will overlap into the row above and below the selected row. Doing this in a the OnPaint of a subclassed
DataGridTextBoxColum dos not seem like a practical way to do it.

I have subclassed a DataGrid and overridden the OnPaint as such:

protected override void OnPaint(PaintEventArgs pe)

{

base.OnPaint(pe);

// Create pen.

Pen blackPen = new Pen(Color.Green, 2);

// Create location and size of rectangle.

float x = 15.0F;

float y = 53.0F;

float width = 500.0F;

float height = 20.0F;

// Draw rectangle to screen.

pe.Graphics.DrawRectangle(blackPen, x, y, width, height);

}

It works but has refresh problems.

Last week Bob Powell [MVP] suggested that I use a NativeWindow class to
solve this problem. I've just had the time to get back to this and not being a former C++ person, etc., etc., etc. maybe someone can help with this.

The MSDN help screen for the NativeWindow class is this link:

http://msdn.microsoft.com/library/de...classtopic.asp
It has an example and in the subclassed NativeWindow constructor it creates a button:

public MyNativeWindow(Form parent)

{

..see help example

}

Can someone advise me on where my code above that paints the Rectangle
should go in this NativeWindow example?


Nov 21 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.