スクリーンのスケーリング時に非表示のスピンボタンの一部が表示される
対象製品
MultiRow for Windows Forms 10.0J
状況
修正済み
詳細
■現象
ディスプレイのDPI(スケーリング)を125%にした時に、数値スピンボタンを非表示にしたNumericUpDownCell の編集時にスピンボタンの一部が右側に表示されます。(クリックすると値が増減します)
■再現手順
1. MultiRowをフォームに配置後、NumericUpDownCell を以下のように設定します。
ShowSpinButton = NotShown
ShowSpinButtonInEditState = false
2. 画面の設定でディスプレイのDPI(スケーリング)を125%に設定します。(一旦サインアウトしないと反映されません)
3. 1.のコードを実行し、NumericUpDownCell のセルを編集状態にすると現象が発生します。
ディスプレイのDPI(スケーリング)を125%にした時に、数値スピンボタンを非表示にしたNumericUpDownCell の編集時にスピンボタンの一部が右側に表示されます。(クリックすると値が増減します)
■再現手順
1. MultiRowをフォームに配置後、NumericUpDownCell を以下のように設定します。
ShowSpinButton = NotShown
ShowSpinButtonInEditState = false
2. 画面の設定でディスプレイのDPI(スケーリング)を125%に設定します。(一旦サインアウトしないと反映されません)
3. 1.のコードを実行し、NumericUpDownCell のセルを編集状態にすると現象が発生します。
回避方法
この問題はService Pack 2(v10.0.4002.2012)で修正されました。
不具合を修正した最新のサービスパックは、アップデートページ からダウンロードできます。
Service Pack 2 未適用のときは以下の回避方法をご検討ください。
NumericUpDownCell はEditコントロールを使用し数値スピンボタン部分を隠しています。GetEditingControlBoundsをオーバーライドし、Editコントロールの境界を調整することで現象を回避できます。
◎サンプルコード(C#)
不具合を修正した最新のサービスパックは、アップデートページ からダウンロードできます。
Service Pack 2 未適用のときは以下の回避方法をご検討ください。
NumericUpDownCell はEditコントロールを使用し数値スピンボタン部分を隠しています。GetEditingControlBoundsをオーバーライドし、Editコントロールの境界を調整することで現象を回避できます。
◎サンプルコード(C#)
Form1.Designer.cs
using GrapeCity.Win.MultiRow;
using System;
using System.Configuration;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace MultiRowSampleProject
{
partial class Form1
{
/// <summary>
/// 必要なデザイナー変数です。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 使用中のリソースをすべてクリーンアップします。
/// </summary>
/// <param name="disposing">マネージ リソースを破棄する場合は true を指定し、その他の場合は false を指定します。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows フォーム デザイナーで生成されたコード
/// <summary>
/// デザイナー サポートに必要なメソッドです。このメソッドの内容を
/// コード エディターで変更しないでください。
/// </summary>
private void InitializeComponent()
{
this.gcMultiRow1 = new GrapeCity.Win.MultiRow.GcMultiRow();
this.template11 = new MultiRowSampleProject.Template1();
((System.ComponentModel.ISupportInitialize)(this.gcMultiRow1)).BeginInit();
this.SuspendLayout();
//
// gcMultiRow1
//
this.gcMultiRow1.Dock = System.Windows.Forms.DockStyle.Fill;
this.gcMultiRow1.Location = new System.Drawing.Point(0, 0);
this.gcMultiRow1.Name = "gcMultiRow1";
this.gcMultiRow1.Size = new System.Drawing.Size(302, 193);
this.gcMultiRow1.TabIndex = 0;
this.gcMultiRow1.Template = this.template11;
this.gcMultiRow1.Text = "gcMultiRow1";
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 17F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(302, 193);
this.Controls.Add(this.gcMultiRow1);
this.Font = new System.Drawing.Font("MS ゴシック", 10F);
this.Name = "Form1";
this.Text = "Form1";
((System.ComponentModel.ISupportInitialize)(this.gcMultiRow1)).EndInit();
this.ResumeLayout(false);
}
#endregion
private GrapeCity.Win.MultiRow.GcMultiRow gcMultiRow1;
private Template1 template11;
}
public class CustomNumericUpDownCell : NumericUpDownCell
{
protected override Rectangle GetEditingControlBounds(Rectangle cellBounds, int rowIndex)
{
var rect = base.GetEditingControlBounds(cellBounds, rowIndex);
if (!ShowSpinButtonInEditState)
{
var spinWidth = 16;
var field = typeof(UpDownBase).GetField("defaultButtonsWidth", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
if (field != null)
{
spinWidth = (int)field.GetValue(null);
}
var offset = CustomDpiHelper.ScaleX(spinWidth) - spinWidth;
rect.Width += offset;
}
return rect;
}
}
public static class CustomDpiHelper
{
private static float _logicDpiX;
private static float _deviceDpiX;
static CustomDpiHelper()
{
_logicDpiX = 96;
_deviceDpiX = 96;
try
{
if (string.Equals(ConfigurationManager.AppSettings.Get("EnableWindowsFormsHighDpiAutoResizing"), "true", StringComparison.InvariantCultureIgnoreCase))
{
IntPtr hdc = UnsafeNativeMethods.GetDC(IntPtr.Zero);
if (hdc != IntPtr.Zero)
{
_deviceDpiX = UnsafeNativeMethods.GetDeviceCaps(hdc, 88);
UnsafeNativeMethods.ReleaseDC(IntPtr.Zero, hdc);
}
}
}
catch
{
return;
}
}
public static int ScaleX(int x)
{
return (int)Math.Round(_deviceDpiX / _logicDpiX * x, MidpointRounding.AwayFromZero);
}
}
[System.Security.SuppressUnmanagedCodeSecurity()]
internal static partial class UnsafeNativeMethods
{
[DllImport("user32.dll")]
public static extern System.IntPtr GetDC(System.IntPtr hWnd);
[DllImport("gdi32.dll")]
public static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
[DllImport("user32.dll")]
public static extern int ReleaseDC(System.IntPtr hWnd, System.IntPtr hDC);
}
}
using GrapeCity.Win.MultiRow;
using System;
using System.Configuration;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace MultiRowSampleProject
{
partial class Form1
{
/// <summary>
/// 必要なデザイナー変数です。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 使用中のリソースをすべてクリーンアップします。
/// </summary>
/// <param name="disposing">マネージ リソースを破棄する場合は true を指定し、その他の場合は false を指定します。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows フォーム デザイナーで生成されたコード
/// <summary>
/// デザイナー サポートに必要なメソッドです。このメソッドの内容を
/// コード エディターで変更しないでください。
/// </summary>
private void InitializeComponent()
{
this.gcMultiRow1 = new GrapeCity.Win.MultiRow.GcMultiRow();
this.template11 = new MultiRowSampleProject.Template1();
((System.ComponentModel.ISupportInitialize)(this.gcMultiRow1)).BeginInit();
this.SuspendLayout();
//
// gcMultiRow1
//
this.gcMultiRow1.Dock = System.Windows.Forms.DockStyle.Fill;
this.gcMultiRow1.Location = new System.Drawing.Point(0, 0);
this.gcMultiRow1.Name = "gcMultiRow1";
this.gcMultiRow1.Size = new System.Drawing.Size(302, 193);
this.gcMultiRow1.TabIndex = 0;
this.gcMultiRow1.Template = this.template11;
this.gcMultiRow1.Text = "gcMultiRow1";
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 17F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(302, 193);
this.Controls.Add(this.gcMultiRow1);
this.Font = new System.Drawing.Font("MS ゴシック", 10F);
this.Name = "Form1";
this.Text = "Form1";
((System.ComponentModel.ISupportInitialize)(this.gcMultiRow1)).EndInit();
this.ResumeLayout(false);
}
#endregion
private GrapeCity.Win.MultiRow.GcMultiRow gcMultiRow1;
private Template1 template11;
}
public class CustomNumericUpDownCell : NumericUpDownCell
{
protected override Rectangle GetEditingControlBounds(Rectangle cellBounds, int rowIndex)
{
var rect = base.GetEditingControlBounds(cellBounds, rowIndex);
if (!ShowSpinButtonInEditState)
{
var spinWidth = 16;
var field = typeof(UpDownBase).GetField("defaultButtonsWidth", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
if (field != null)
{
spinWidth = (int)field.GetValue(null);
}
var offset = CustomDpiHelper.ScaleX(spinWidth) - spinWidth;
rect.Width += offset;
}
return rect;
}
}
public static class CustomDpiHelper
{
private static float _logicDpiX;
private static float _deviceDpiX;
static CustomDpiHelper()
{
_logicDpiX = 96;
_deviceDpiX = 96;
try
{
if (string.Equals(ConfigurationManager.AppSettings.Get("EnableWindowsFormsHighDpiAutoResizing"), "true", StringComparison.InvariantCultureIgnoreCase))
{
IntPtr hdc = UnsafeNativeMethods.GetDC(IntPtr.Zero);
if (hdc != IntPtr.Zero)
{
_deviceDpiX = UnsafeNativeMethods.GetDeviceCaps(hdc, 88);
UnsafeNativeMethods.ReleaseDC(IntPtr.Zero, hdc);
}
}
}
catch
{
return;
}
}
public static int ScaleX(int x)
{
return (int)Math.Round(_deviceDpiX / _logicDpiX * x, MidpointRounding.AwayFromZero);
}
}
[System.Security.SuppressUnmanagedCodeSecurity()]
internal static partial class UnsafeNativeMethods
{
[DllImport("user32.dll")]
public static extern System.IntPtr GetDC(System.IntPtr hWnd);
[DllImport("gdi32.dll")]
public static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
[DllImport("user32.dll")]
public static extern int ReleaseDC(System.IntPtr hWnd, System.IntPtr hDC);
}
}