{"id":1736,"date":"2008-02-06T23:47:17","date_gmt":"2008-02-07T03:47:17","guid":{"rendered":"http:\/\/www.hoogervorst.ca\/arthur\/?p=1736"},"modified":"2008-02-07T21:17:04","modified_gmt":"2008-02-08T01:17:04","slug":"owner-draw-ii","status":"publish","type":"post","link":"http:\/\/www.hoogervorst.ca\/arthur\/?p=1736","title":{"rendered":"Owner-draw (II)"},"content":{"rendered":"<p><span class=\"dropcap\">E<\/span>arlier, <a href='http:\/\/www.hoogervorst.ca\/arthur\/?attachment_id=1737' rel='attachment wp-att-1737' title='An owner-draw grid'><img class=\"alignright\" src='http:\/\/www.hoogervorst.ca\/arthur\/wp-content\/uploads\/2008\/02\/own_er_draw_grid.thumbnail.jpg' alt='An owner-draw grid' \/><\/a>which is, almost a year ago, I was comparing owner-draw programming in Delphi and C# and concluded that <a href=\"http:\/\/www.hoogervorst.ca\/arthur\/?p=1425\">it&#8217;s quite similar<\/a>:  basically you set any visual component in a particular mode (&#8216;I&#8217;m going to take care of drawing the content&#8217;) and then you basically override the component&#8217;s OnPaint\/OnDraw event. Drawing the actual stuff is the hardest part, but there&#8217;s pretty good API help for both Win32 and .Net platforms. If you have programmed graphics in Win32 before, this is going to be a piece of pie.\n<\/p>\n<p>So, yeah: a couple of years ago, I did some fancy stuff in a Delphi <a href=\"http:\/\/www.hoogervorst.ca\/arthur\/?p=604\">Drawgrid component<\/a>. The .Net framework has a similar &#8216;grid&#8217; like component, which is called a &#8216;Datagridview&#8217; and you probably guessed it: it has basically the same functionality and offers the (almost) the same features as Delphi&#8217;s DrawGrid component. This brings me to that earlier mentioned project I was working on: a Sudoku puzzle generator, which obviously needed to use a custom grid-like component with a lot of colours (Warning: if you&#8217;re not interested in programming, you probably don&#8217;t want to continue reading).\n<\/p>\n<p><!--more--><\/p>\n<p>Before you go copy and paste the code into your project: the moment that you start overriding the dataGridView&#8217;s CellPaint event, <em>you are in charge of drawing everything that has to do with the grid&#8217;s cells<\/em>. This means that you should be aware of the fact that each cell can have different states: for example, cells can be selected, frozen, read-only or a mix of all these states at the same time (Look for the DataGridViewElementStates Enumeration). You are going to have to test each cell&#8217;s state for each particular state that you planned to take care of. In the sample below, I&#8217;m only testing for the <em>Selected <\/em>and <em>Displayed<\/em> state: When a user selects a cell, the border will get a nice thick orange border. In other cases, cells should be drawn as much as Sudoku puzzles look like in your daily paper: that is, after every 3 columns and rows, there&#8217;s going to be a nice thick line that separates each 3&#215;3 grid from the one next to it.\n<\/p>\n<p><pre>\r\n        private void dataGridView1_CellPainting(object sender, \r\n               DataGridViewCellPaintingEventArgs e)\r\n        {\r\n            using (Brush backColorBrush = \r\n                       new SolidBrush(e.CellStyle.BackColor),\r\n                  gridBrush = \r\n                       new SolidBrush(this.dataGridView1.GridColor))\r\n            {\r\n\r\n                using (Pen gridLinePen = new Pen(gridBrush))\r\n                {\r\n\r\n\r\n                    int x = e.ColumnIndex + 1;\r\n                    int y = e.RowIndex + 1;\r\n\r\n\r\n                    \/\/ 1. Draw the background first.\r\n                    e.Graphics.FillRectangle(backColorBrush, e.CellBounds);                    \r\n\r\n                    \/\/ 2. Test if the cell is selected\r\n                    if ((e.State & DataGridViewElementStates.Selected) \r\n                         == DataGridViewElementStates.Selected)\r\n                    {\r\n                        \r\n                        \/\/ Draw Orange stuff...\r\n                        gridLinePen.Width = 3;\r\n                        gridLinePen.Color = Color.Orange;\r\n                        e.Graphics.FillRectangle(Brushes.NavajoWhite, \r\n                             e.CellBounds);\r\n\r\n                        e.Graphics.DrawRectangle(gridLinePen, \r\n                            e.CellBounds.Left + 1,\r\n                            e.CellBounds.Top + 1, \r\n                            e.CellBounds.Width - 4, \r\n                            e.CellBounds.Height - 4);\r\n\r\n                        if (((x % 3) == 0) && (x != 0))\r\n                        {\r\n                            gridLinePen.Width = 3;\r\n                            gridLinePen.Color = Color.Navy;\r\n                            e.Graphics.DrawLine(gridLinePen,\r\n                               e.CellBounds.Right - 1, e.CellBounds.Top,\r\n                                e.CellBounds.Right - 1, e.CellBounds.Bottom);\r\n\r\n                        }\r\n                        else\r\n                        {\r\n                            gridLinePen.Width = 1;\r\n                            gridLinePen.Color = this.dataGridView1.GridColor;\r\n                            e.Graphics.DrawLine(gridLinePen,\r\n                                e.CellBounds.Right - 1, e.CellBounds.Top,\r\n                                e.CellBounds.Right - 1, e.CellBounds.Bottom);\r\n                        }\r\n\r\n                        if (((y % 3) == 0) && (y != 0))\r\n                        {\r\n                            gridLinePen.Width = 3;\r\n                            gridLinePen.Color = Color.Navy;\r\n                            e.Graphics.DrawLine(gridLinePen,\r\n                                e.CellBounds.Left, e.CellBounds.Bottom - 1, \r\n                                e.CellBounds.Right - 1,\r\n                                e.CellBounds.Bottom - 1);\r\n                        }\r\n                        else\r\n                        {\r\n                            gridLinePen.Width = 1;\r\n                            gridLinePen.Color = this.dataGridView1.GridColor;\r\n                            e.Graphics.DrawLine(gridLinePen,\r\n                                e.CellBounds.Left, e.CellBounds.Bottom - 1, \r\n                                e.CellBounds.Right - 1,\r\n                                e.CellBounds.Bottom - 1);\r\n                        }\r\n\r\n                        \/\/ Draw the actual data....\r\n                        if (e.Value != null)\r\n                        {\r\n\r\n                            StringFormat np = new StringFormat(StringFormat.GenericDefault);\r\n                            np.Alignment = StringAlignment.Center;\r\n                            np.LineAlignment = StringAlignment.Center;\r\n\r\n                            e.Graphics.DrawString(e.Value.ToString(), e.CellStyle.Font,\r\n                                Brushes.Orange, e.CellBounds, np);\r\n                        }\r\n\r\n                    }\r\n\r\n                    \/\/ 3. Draw normal cells...\r\n                    if ((e.State &  DataGridViewElementStates.Displayed) \r\n                        == DataGridViewElementStates.Displayed)                    \r\n                    {                    \r\n\r\n                        if ((x % 3) == 0 && (x != 9))\r\n                        {\r\n                            gridLinePen.Width = 3;\r\n                            gridLinePen.Color = Color.Navy;\r\n                            e.Graphics.DrawLine(gridLinePen,\r\n                               e.CellBounds.Right - 1, e.CellBounds.Top,\r\n                                e.CellBounds.Right - 1, e.CellBounds.Bottom);\r\n\r\n                        }\r\n                        else\r\n                        {\r\n                            gridLinePen.Width = 1;\r\n                            gridLinePen.Color = this.dataGridView1.GridColor;\r\n                            e.Graphics.DrawLine(gridLinePen,\r\n                                e.CellBounds.Right - 1, e.CellBounds.Top,\r\n                                e.CellBounds.Right - 1, e.CellBounds.Bottom);\r\n                        }\r\n\r\n                        if (((y % 3) == 0) && (y != 9))\r\n                        {\r\n                            gridLinePen.Width = 3;\r\n                            gridLinePen.Color = Color.Navy;\r\n                            e.Graphics.DrawLine(gridLinePen,\r\n                                e.CellBounds.Left, e.CellBounds.Bottom - 1, \r\n                                e.CellBounds.Right - 1,\r\n                                e.CellBounds.Bottom - 1);\r\n                        }\r\n                        else\r\n                        {\r\n                            gridLinePen.Width = 1;\r\n                            gridLinePen.Color = this.dataGridView1.GridColor;\r\n                            e.Graphics.DrawLine(gridLinePen,\r\n                                e.CellBounds.Left, e.CellBounds.Bottom - 1, \r\n                                e.CellBounds.Right - 1,\r\n                                e.CellBounds.Bottom - 1);\r\n                        }\r\n\r\n\r\n                        \/\/ Draw the actual data.\r\n                        if (((e.State & DataGridViewElementStates.Selected) \r\n                            == DataGridViewElementStates.Selected) == false)\r\n                        {\r\n                           e.PaintContent(e.ClipBounds);\r\n                        }\r\n                        \r\n                    }\r\n                }                \r\n            }\r\n            e.Handled = true;\r\n        }\r\n<\/pre>\n<\/p>\n<p>Note that .Net supports specific portions of a cell to be drawn automatically (or rather by the system itself), which will save you some headaches: for example normal cells (the ones that have the Cellstate of &#8216;displayed&#8217;) I use the e.PaintContent method to force the component to paint the content.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Earlier, which is, almost a year ago, I was comparing owner-draw programming in Delphi and C# and concluded that it&#8217;s quite similar: basically you set any visual component in a particular mode (&#8216;I&#8217;m going to take care of drawing the &hellip; <a href=\"http:\/\/www.hoogervorst.ca\/arthur\/?p=1736\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[4],"tags":[56,88,274],"_links":{"self":[{"href":"http:\/\/www.hoogervorst.ca\/arthur\/index.php?rest_route=\/wp\/v2\/posts\/1736"}],"collection":[{"href":"http:\/\/www.hoogervorst.ca\/arthur\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.hoogervorst.ca\/arthur\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.hoogervorst.ca\/arthur\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.hoogervorst.ca\/arthur\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1736"}],"version-history":[{"count":0,"href":"http:\/\/www.hoogervorst.ca\/arthur\/index.php?rest_route=\/wp\/v2\/posts\/1736\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.hoogervorst.ca\/arthur\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1736"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.hoogervorst.ca\/arthur\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1736"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.hoogervorst.ca\/arthur\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1736"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}