Click here to Skip to main content
15,887,027 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
I am having a problem drawing in the titlebar and border in Windows 7. The code below works fine in XP, but fails in Windows 7. Interestingly, if I place this code into a form and inherit it from another form, I can see the graphics drawing at design time. But when I run the app and display the form the graphics go away. Does anyone know what I can do to fix this so that it works in Windows 7.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WindowsFormsApplication1
{
	public partial class Form1 : Form
	{
		public Form1() {
			InitializeComponent();
		}

		[DllImport("user32.dll")]
		static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);

		[DllImport("User32.dll")]

		private static extern IntPtr GetWindowDC(IntPtr hWnd);

		protected override void WndProc(ref System.Windows.Forms.Message m) {
			
			const int WM_NCPAINT = 0x85;
			const int WM_NCCREATE = 0x0081;
			const int WM_NCCALCSIZE = 0x0083;
			const int WM_NCACTIVATE = 0x0086;

			SolidBrush myBrush;

			base.WndProc(ref m);
			if (m.Msg == WM_NCACTIVATE || m.Msg == WM_NCPAINT || m.Msg == WM_NCCREATE || m.Msg == WM_NCCALCSIZE) {
				IntPtr hdc = GetWindowDC(m.HWnd);
				if ((int)hdc != 0) {
					Graphics g = Graphics.FromHdc(hdc);

					myBrush = new SolidBrush(SystemColors.ActiveCaption);
					Pen myPen = new Pen(myBrush, 5);
					
					myBrush = new SolidBrush(Color.FromArgb(255, 255, 0, 0));
					g.FillRectangle(myBrush, 0, 0, 150, SystemInformation.CaptionHeight); 

					myBrush = new SolidBrush(Color.FromArgb(120, 255, 0, 0));
					myPen = new Pen(myBrush, 2);
					g.DrawRectangle(myPen, 0, 1, 150, SystemInformation.CaptionHeight);

					myBrush = new SolidBrush(Color.FromArgb(255, 255, 0, 0));
					g.FillEllipse(myBrush, 150 - 20, 0, 30, SystemInformation.CaptionHeight); 

					myBrush = new SolidBrush(Color.FromArgb(80, 255, 0, 0));
					g.FillEllipse(myBrush, 150 - 17, 1, 30, SystemInformation.CaptionHeight + 1); 

					myBrush = new SolidBrush(Color.FromArgb(150, 255, 0, 0));
					myPen = new Pen(myBrush, SystemInformation.FrameBorderSize.Width * 2);
					g.DrawRectangle(myPen, 0, 0, this.Width, this.Height);


					myBrush = new SolidBrush(Color.White);
					Font myFont = new Font(new FontFamily("Arial"), 18, FontStyle.Bold, GraphicsUnit.Pixel);
					g.DrawString("Some Text", myFont, myBrush, 5, 3);

					g.Flush();
					ReleaseDC(m.HWnd, hdc);
				}
			}

		}


	}
}
Posted
Comments
Sergey Alexandrovich Kryukov 24-May-13 10:49am    
Interesting problem; voted 5 for a question.
—SA
chellapandi160 20-Apr-16 2:02am    
Hi,
I'm using windows 7 Professional But, It's working fine..

1 solution

As I say, the question is interesting, but going in for resolving it I think is too boring. :-)

My idea is: the effects you can achieve in best case are very limiting anyway, but by using such effects you badly sacrifice platform compatibility of your code.

The usual (and I think, practical) workaround is this: create a form without title bar and borders and mimic all non-client area by custom controls placed in client area. From the stylistic point of view, you should not try to follow regular windows styles, even though you could check with system-wide windows metrics. Just the opposite: the style should stand out and be independent on system-wide UI style. You can even easily make non-rectangular window and its inner elements.

I'm pretty much sure you knew about this possibility. I merely tried to convince you that it makes practical sense, while the idea to paint non-client areas is questionable. Leave other, regular windows to Aero, which you hardly can mimic anyway, do something of your own without platform incompatibilities.

—SA
 
Share this answer
 
v2
Comments
Sergey Alexandrovich Kryukov 24-May-13 16:31pm    
[OP commented as solution, but as it should be removed, I moved it here — SA]

Thanks for the feedback Sergey. I do understand and agree with your points

But just for kicks, do you happen to know how to prevent the graphics from getting drawn over after they are created? For reasons that I do not understand after I override the message and draw the graphics they get drawn over again with the original winform border. I am guessing that I need to somehow prevent the subsequent painting by windows when I override, but I cannot figure out how.

Thanks for taking the time to look at this!
Sergey Alexandrovich Kryukov 24-May-13 16:34pm    
First of all, please don't post such comments as "solution". You see someone down-voted it, and there will be abuse reports, which you don't want. This post will eventually be removed, so I'll comment on my answer.

I did not see your post, because only a person only gets notification if you comment this person's post or reply to existing comment.

Anyway, are you accepting this answer formally (green button)?

As to your follow-up question, it's hard to me to explain re-drawing at this moment; I did non-client drawing; and it worked correctly for me (even though I avoid it). Re-drawing is generally driven by invalidation of an area. Just for some food for thought:

http://stackoverflow.com/questions/2819937/invalidating-non-client-areas

—SA
wcb2@cornell.edu 24-May-13 16:50pm    
I should also add that this is for an in house application and all 20 or so users will be on windows 7. So all the concerns about multiple platform compatibility are really not concerns for me. This is for an order management application where there are multiple user accounts in which orders can occur. So, the users will have multiple instances of the app running for each account and I need to visually distinguish which instances is for which account.

It would be ideal if each window had a big fat title bar with a color and some text indicating the account. If I go borderless, I lose some built in behaviours and introduce a whole bunch of other issues that need to be dealt with in code. So, this is why I want keep the border and just draw the indicator graphics. All I need to do is figure out how to keep Windows 7 from drawing over the graphics after overriding the NC messages.

I realize its a boring topic, but instead of suggesting that go in another direction I would be very grateful if someone would consider the underlying question: How to stop WIndows 7 from drawing over the NC graphics after they are created.
Sergey Alexandrovich Kryukov 24-May-13 16:55pm    
Here is the apparent point: this behaviors you loose with loosing a title bare are much, much easier to reproduce than solving the problem with modification of non-client rendering!
—SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900