|
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
|
|
|
|
|
|
Why you use this const? Is there any way to check width of this 'dropdown button'? I have bigger fonts than normal - and there is small part of normal 3D button
|
|
|
|
|
I used:
int DROPDOWNWIDTH = ctrl.Height-2;
in my situation it helped - work for normal and large fonts.
|
|
|
|
|
Hi,
I haven't tried the approach you suggested, but it is great knowing that it works for you.
When it come to adjusting for drawing, I tempt to use the graphic resolution, so say "g" is the Graphics object, I would do something like this:
int iWidth = (int) ((g.DpiX/96.0f) * DROPDOWNWIDTH);
I use 96 there because that is the pixel size for standard font display. I also make it a float so that we keep the precision when performing the math.
Cheers,
Fadrian
|
|
|
|
|
Hi Fadrian, I am trying to use your Flat combo in VB.net. But I am very confused, can u help me out?
If you can give me any code (as simple as this one). I will be very thankful to u...
KingVikram
|
|
|
|
|
Hi,
All the code logic will be the same, it is just the mapping of C# code to VB.NET flavour. Unfortunately, I don't have any VB.NET class handy for this control, so you may have to write one yourself. Alternatively, you can make this library and used it in your VB.NET project.
Cheers,
Fadrian
|
|
|
|
|
Hi all
Here it is, the basic flavour.
Still there are 3 questions open, as I did not understand quite well the C#-syntax. The code worked fine for me, but still it would be great if you could approve it
Duc_de_Belfort
'Questions: Are the translations correct??
'1. Question:
'if (ctrl.Focused == false || ctrl.Enabled == false )
'translated as:
' If (ctrl.Focused = False Or ctrl.Enabled = False) Then
'2. Question (what the hell is: this.enabled? BackColor: ... ????)
'Pen p = new Pen((this.Enabled? BackColor:SystemColors.Control), 2)
'translated as:
'Dim p As Pen = New Pen(Me.BackColor, 3)
'3. Question
'Public FlatComboBox()
' : base()
' {
' this.SetStyle(ControlStyles.DoubleBuffer, true);
' }
'translated as:
'Public Sub New()
' MyBase.New()
' Me.SetStyle(ControlStyles.DoubleBuffer, True)
'End Sub
Imports System
Imports System.Windows.Forms
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Runtime.InteropServices
Public Class FlatComboBox
Inherits ComboBox
Public Const WM_ERASEBKGND As Integer = &H14
Public Const WM_PAINT As Integer = &HF
Public Const WM_NC_PAINT As Integer = &H85
Public Const WM_PRINTCLIENT As Integer = &H318
Declare Function SendMessage Lib "user32" Alias _
"SendMessageA" (ByVal hWnd As IntPtr, ByVal wMsg As Long, _
ByVal wParam As IntPtr, ByVal lParam As Object) As Long
Declare Function GetWindowDC Lib "user32" (ByVal hwnd As IntPtr) As IntPtr
Declare Function ReleaseDC Lib "user32" (ByVal hwnd As IntPtr, ByVal hDC As IntPtr) As Long
Public Sub New()
MyBase.New()
Me.SetStyle(ControlStyles.DoubleBuffer, True)
End Sub
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If (Me.DropDownStyle = ComboBoxStyle.Simple) Then
MyBase.WndProc(m)
Else
Dim hdc As IntPtr = GetWindowDC(Me.Handle)
Dim gdc As Graphics = Graphics.FromHdc(hdc)
Select Case m.Msg
Case WM_NC_PAINT
SendMessage(Me.Handle, WM_ERASEBKGND, hdc, 0)
SendPrintClientMsg() ' send to draw client area
PaintFlatControlBorder(Me, gdc)
m.Result = New IntPtr(1) ' indicate msg has been processed
Case WM_PAINT
MyBase.WndProc(m)
' flatten the border area again
Dim p As Pen = New Pen(Me.BackColor, 3)
gdc.DrawRectangle(p, New Rectangle(2, 2, Me.Width - 3, Me.Height - 3))
PaintFlatDropDown(Me, gdc)
PaintFlatControlBorder(Me, gdc)
Case Else
MyBase.WndProc(m)
End Select
ReleaseDC(m.HWnd, hdc)
gdc.Dispose()
End If
End Sub
Private Sub SendPrintClientMsg()
' We send this message for the control to redraw the client area
Dim gClient As Graphics = Me.CreateGraphics()
Dim ptrClientDC As IntPtr = gClient.GetHdc()
SendMessage(Me.Handle, WM_PRINTCLIENT, ptrClientDC, 0)
gClient.ReleaseHdc(ptrClientDC)
gClient.Dispose()
End Sub
Private Sub PaintFlatControlBorder(ByVal ctrl As Control, ByVal g As Graphics)
Dim rect As Rectangle = New Rectangle(0, 0, ctrl.Width, ctrl.Height)
If (ctrl.Focused = False Or ctrl.Enabled = False) Then 'how is || transmitted: & or or?
ControlPaint.DrawBorder(g, rect, SystemColors.ControlDark, ButtonBorderStyle.Solid)
Else
ControlPaint.DrawBorder(g, rect, Color.Black, ButtonBorderStyle.Solid)
End If
End Sub
Public Sub PaintFlatDropDown(ByVal ctrl As Control, ByVal g As Graphics)
Const DROPDOWNWIDTH As Integer = 18
Dim rect As Rectangle = New Rectangle(ctrl.Width - DROPDOWNWIDTH, 0, DROPDOWNWIDTH, ctrl.Height)
ControlPaint.DrawComboButton(g, rect, ButtonState.Flat)
End Sub
Protected Overrides Sub OnSelectedValueChanged(ByVal e As System.EventArgs)
MyBase.OnSelectedValueChanged(e)
Me.Invalidate()
End Sub
Protected Overrides Sub OnLostFocus(ByVal e As System.EventArgs)
MyBase.OnLostFocus(e)
Me.Invalidate()
End Sub
Protected Overrides Sub OnGotFocus(ByVal e As System.EventArgs)
MyBase.OnGotFocus(e)
Me.Invalidate()
End Sub
Protected Overrides Sub OnResize(ByVal e As System.EventArgs)
MyBase.OnResize(e)
Me.Invalidate()
End Sub
End Class
|
|
|
|
|
Sorry for the late reply.
OK, answer to your questions in order:
1. Correct
2. Conditional Statement. It is like a shorthand to if else statement. You will write in VB as
If (Enabled = True) Then
pen = new Pen(Me.BackColor, 2)
Else
pen = new Pen(SystemColors.Control, 2)
EndIf
3. Correct
I skim through the code and it looks OK
|
|
|
|
|
Hi Fadrian
Thanks for your answer. I c the meaning now.
But let me as vb-guy point out that we (in the vb-world) as well can write the sentence in one line:
Dim p As Pen = New Pen(IIf(Enabled, Me.BackColor, SystemColors.Control), 2)
Cheers,
Duc
PS: Thanks for your contribution again!
|
|
|
|
|
Hi Fadrian
Thanks for your answer. I c the meaning now.
But let me as vb-guy point out that we (in the vb-world) as well can write the sentence in one line:
Dim p As Pen = New Pen(IIf(Me.Enabled, Me.BackColor, SystemColors.Control), 2)
Cheers,
Duc
PS: Thanks for your contribution again!
|
|
|
|
|
Compiling your C# code down to a dll, and importing it into my project as a Reference works fine also, without having to convert it to VB.Net.
Add this to the code:
Imports DrawFlat.FlatComboBox
'then in the vb code change
Me.ComboBox1 = New System.Windows.Forms.ComboBox
'to this:
Me.ComboBox1 = New DrawFlat.FlatComboBox
'works like a charm
Elizabeth Gee
Information Architect - .Net Developer
http://www.nwtd.com
|
|
|
|
|
Liz,
Glad to hear that it works well for you, although I have seen a new bug just being reported by you I will answer that soon.
Fadrian
|
|
|
|
|
Hi Fadrian. I've downloaded your classs and I realized that it doesn't displays correctly when the form is resized. I've made a little change and overrided the OnResize method calling Invalidate():
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
this.Invalidate();
}
Making this change the control resizes correctly.
Ricardo
|
|
|
|
|