|
|
Comments and Discussions
|
|
 |

|
I have a Sony Vaio with 1900x1200 resolution.
This FlatCombobox works great, except there is an odd artifact:
Ther is a wide 3D gap showing between the Textbox portion of the control and the arrow part of the control.
Any ideas on this? I tried it as a C# dll and also with the VB.Net code snippet. They both do the same thing.
Elizabeth Gee
Information Architect - .Net Developer
http://www.nwtd.com
|
|
|
|

|
Liz,
AutoScale can be nasty and I constantly run into problem with it.
Can you capture the screen of the 3D wide artifact problem and send to my email a/c? Once I see the exact prob, I may be able to make other suggestion.
Fadrian
|
|
|
|

|
Here is a link to a screenshot of your Flat Combo on my Sony Vaio at 16oox1200 resolution:
http://www32.brinkster.com/icontoo/Temp/FlatComboOnSonyVaio.html
Also, here is your code with the two modifications made by others, which I compiled down to a C# DLL as depicted in the screenshot:
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
namespace DrawFlat
{
[ToolboxBitmap(typeof(System.Windows.Forms.ComboBox))]
public class FlatComboBox: ComboBox
{
public const int WM_ERASEBKGND = 0x14;
public const int WM_PAINT = 0xF;
public const int WM_NC_PAINT = 0x85;
public const int WM_PRINTCLIENT = 0x318;
[DllImport("user32.dll", EntryPoint="SendMessageA")]
public static extern int SendMessage (IntPtr hwnd, int wMsg, IntPtr wParam, object lParam);
[DllImport("user32")]
public static extern IntPtr GetWindowDC (IntPtr hWnd );
[DllImport("user32")]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC );
public FlatComboBox()
: base()
{
this.SetStyle(ControlStyles.DoubleBuffer, true);
}
protected override void OnSelectedValueChanged(EventArgs e)
{
base.OnSelectedValueChanged (e);
this.Invalidate();
}
protected override void WndProc(ref Message m)
{
if (this.DropDownStyle == ComboBoxStyle.Simple)
{
base.WndProc(ref m);
return;
}
IntPtr hDC = GetWindowDC(this.Handle);
Graphics gdc = Graphics.FromHdc(hDC);
switch (m.Msg)
{
case WM_NC_PAINT:
SendMessage(this.Handle, WM_ERASEBKGND, hDC, 0);
SendPrintClientMsg(); // send to draw client area
PaintFlatControlBorder(this, gdc);
m.Result = (IntPtr) 1; // indicate msg has been processed
break;
case WM_PAINT:
base.WndProc(ref m);
// flatten the border area again
Pen p = new Pen((this.Enabled? BackColor:SystemColors.Control), 2);
gdc.DrawRectangle(p, new Rectangle(2, 2, this.Width-3, this.Height-3));
PaintFlatDropDown(this, gdc);
PaintFlatControlBorder(this, gdc);
break;
default:
base.WndProc(ref m);
break;
}
ReleaseDC(m.HWnd, hDC);
gdc.Dispose();
}
private void SendPrintClientMsg()
{
// We send this message for the control to redraw the client area
Graphics gClient = this.CreateGraphics();
IntPtr ptrClientDC = gClient.GetHdc();
SendMessage(this.Handle, WM_PRINTCLIENT, ptrClientDC, 0);
gClient.ReleaseHdc(ptrClientDC);
gClient.Dispose();
}
private void PaintFlatControlBorder(Control ctrl, Graphics g)
{
Rectangle rect = new Rectangle(0, 0, ctrl.Width, ctrl.Height);
if (ctrl.Focused == false || ctrl.Enabled == false )
ControlPaint.DrawBorder(g, rect, SystemColors.ControlDark, ButtonBorderStyle.Solid);
else
ControlPaint.DrawBorder(g, rect, Color.Black, ButtonBorderStyle.Solid);
}
public static void PaintFlatDropDown(Control ctrl, Graphics g)
{
const int DROPDOWNWIDTH = 18;
int iWidth = (int) ((g.DpiX/96.0f) * DROPDOWNWIDTH);
//Rectangle rect = new Rectangle(ctrl.Width-DROPDOWNWIDTH, 0, DROPDOWNWIDTH, ctrl.Height);
Rectangle rect = new Rectangle(ctrl.Width-iWidth, 0, iWidth, ctrl.Height);
ControlPaint.DrawComboButton(g, rect, ButtonState.Flat);
}
protected override void OnLostFocus(System.EventArgs e)
{
base.OnLostFocus(e);
this.Invalidate();
}
protected override void OnGotFocus(System.EventArgs e)
{
base.OnGotFocus(e);
this.Invalidate();
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
this.Invalidate();
}
}
}
Elizabeth Gee
Information Architect - .Net Developer
http://www.nwtd.com
|
|
|
|

|
Liz,
Looks like the width of the dropdown combo is 1 pixel out. I would just change the DROPDOWNWIDTH to 19. It doesn't really matter in normal screen display for the dropdown combo to be 1 pixel wider. Perhaps 19 would be a better size to be used as it will cover the standard 17 pixel width combo and total of 2 3D pixels outer border for the left and right.
Fadrian
|
|
|
|

|
Beautiful!
I changed the DROPDOWNWIDTH from 18 to 20 then tho 21, and 21 closed it up perfectly at 1900x1200 resolution
Thanks!
Elizabeth Gee
Information Architect - .Net Developer
http://www.nwtd.com
|
|
|
|

|
Glad to hear. Hmm... the solution may only work with high res display, and may not view nicely in low res display. I still suspect the problem lies with the AutoScale setting and the font used, but don't take my word for that. I yet to find a programatic way to solve this problem. If anyone knows the answer, I will appreciate your feedback.
|
|
|
|

|
Solved: (Fairly much so)
I tested this on my Sony Vaio at:1920x1200, 1600x1200, and 1280x1024. At the higher two resolutions the below fix works great.
Also on my standard Dell desktop machine at 1280x1024, it works great.
I added a check to your code to check for the Screen Resolution width, and it adjusts the DROPDOWNWIDTH for the resolution above or below 1500.
I compiled this C# into a DLL and then tested it on both machines.
What I ran into was the Sony Vaio does a software screen resolution change, not a hardware one, thus when I set the Sony Vaio to 1280x1024, get that small vertical artifact between the textbox and the arrow parts of the combo box.
All the rest of the code I left the same as the last time I posted it on this thread. I included the VB.Net and C#.Net variations of this code snippet below...
[Visual Basic.Net]
Public Sub PaintFlatDropDown(ByVal ctrl As Control, ByVal g As Graphics)
Dim DROPDOWNWIDTH As Integer
Dim scrRes As Screen
Dim intScrWidth As Integer
intScrWidth = scrRes.PrimaryScreen.Bounds.Width
If (intScrWidth < 1500) Then
DROPDOWNWIDTH = 18
Else
DROPDOWNWIDTH = 21
End If
Dim rect As Rectangle = New Rectangle(ctrl.Width - DROPDOWNWIDTH, 0, DROPDOWNWIDTH, ctrl.Height)
ControlPaint.DrawComboButton(g, rect, ButtonState.Flat)
End Sub
[C#.Net]
public static void PaintFlatDropDown(Control ctrl, Graphics g)
{
int DROPDOWNWIDTH = 18;
Screen screen = Screen.PrimaryScreen;
if (screen.Bounds.Width > 1500)
DROPDOWNWIDTH = 21;
int iWidth = (int) ((g.DpiX/96.0f) * DROPDOWNWIDTH);
//Rectangle rect = new Rectangle(ctrl.Width-DROPDOWNWIDTH, 0, DROPDOWNWIDTH, ctrl.Height);
Rectangle rect = new Rectangle(ctrl.Width-iWidth, 0, iWidth, ctrl.Height);
ControlPaint.DrawComboButton(g, rect, ButtonState.Flat);
}
Elizabeth Gee
Information Architect - .Net Developer
http://www.nwtd.com
|
|
|
|

|
Hi Elizabeth,
You could also try the snippet:
[C# .NET]
public static void PaintFlatDropDown(Control ctrl, Graphics g)
{
Rectangle rect = new Rectangle(ctrl.Width-SystemInformation.VerticalScrollBarWidth, 0, SystemInformation.VerticalScrollBarWidth, ctrl.Height);
ControlPaint.DrawComboButton(g, rect, ButtonState.Flat);
}
It works fine at lower resulutions, and I guess it should also work fine at higher resolutions since it gets the width of the button from the system... you'll also reduce a bit your code.
Best wishes
|
|
|
|

|
Small correction over my own code.
I've just found that my code snippet shows part of the 3D button aswel, but not due to the resolution but due to the OS it's running. On XP it runs perfectlly and it adjusts to the button width, but the 3D presentation of the button on Windows 2000, is a bit different snd it messes up a bit.
To correct this problem and hide the 3D section of the button (Same as your posted image) I did the following extra modification:
[C# .NET]
public static void PaintFlatDropDown(Control ctrl, Graphics g)
{
int myWidth = SystemInformation.VerticalScrollBarWidth;
myWidth += SystemInformation.Border3DSize.Width ;
Rectangle rect = new Rectangle(ctrl.Width-myWidth, 0, myWidth, ctrl.Height);
ControlPaint.DrawComboButton(g, rect, ButtonState.Flat);
}
As you can see I've added the 3D border default width, this hides completelly the button... I've used the variable "myWidth" as you should add a check in order to add the border Width if windows themes are disabled, and if they are enabled we just skip this check.
Best wishes and hope you find it usefull.
And just a question: You're running the control on a Pre-Windows XP, right?
|
|
|
|

|
Hi all,
This maybe a bit late, but I have properly fix this now in the latest version. if you have a chance, give it a try and let me know.
Fadrian
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
|
A simple and easy class that draws the standard ComboBox as flat control.
| Type | Article |
| Licence | |
| First Posted | 6 May 2004 |
| Views | 282,604 |
| Bookmarked | 70 times |
|
|