更改单个应用程序的系统颜色(Windows,.NET)

时间:2009-07-07 12:03:27

标签: .net winapi colors user32 systemcolors

我知道我一般应该避免弄乱这些系统设置,但我的应用程序已经使用了非标准颜色,我对此没有任何影响。我希望能够在某些地方添加标准.NET控件,但它们的颜色不匹配。我想有一个黑客可以替换这个应用程序的系统颜色。另一个需要注意的重要事项是它是一个.NET应用程序。

到目前为止我的(不完整)想法是:

  • 要创建一个代替GetSysColor的代理User32.dll库,但这将非常繁琐(731个函数需要重定向,1个要替换)并且我不知道如何强制我的应用程序使用该特定副本。< / LI>
  • 以某种方式拦截对GetSysColors的调用(不幸的是,它在CLR的某处,我认为)。
  • 以某种方式修改.NET类SystemColors(在内存中?可能吗?)。

你有什么想法,最好(和完整)的方法是什么?

3 个答案:

答案 0 :(得分:4)

  

我希望能够在某些地方添加标准.NET控件,但它们的颜色不匹配。我希望有一个黑客可以替换这个应用程序的系统颜色。

这就像用大锤敲钉子一样。

您可以做的是继承来自您想要使用的每个库存控件的新控件,而不是在系统内部混淆颜色。因此,您可以从库存TextBox控件继承而不是纯文本框来创建自己的ThemedTextBox。您设置此新控件以默认使用应用程序的配色方案,并且因为 仍然是TextBox,就继承结构而言,您可以在任何使用普通文本框的地方使用它,包括在winforms设计师。

答案 1 :(得分:2)

在我的早期,我开发了一个程序,它注册了一个全局消息挂钩到所有者绘制窗口边框 - 我可以主题所有窗口。这对于单个应用程序也应该是可能的。但是,这不是是一项简单的任务。

否则我不认为这是可能的。如何使用Krypton Toolkit等可用的第三方控件?

答案 2 :(得分:-1)

Ext.create('Ext.form.FormPanel', { title : 'Sample TextArea', width : 400, bodyPadding: 10, renderTo : Ext.getBody(), items: [{ xtype : 'textareafield', grow : true, name : 'message', fieldLabel: 'Message', anchor : '100%', numLines : 15, numCharsPerLine: 10, listeners : { change : function(val,b){ var text = val.getValue(); //console.log(text); var lines = text.split(/\r\n|\n|\r/); for (var i = 0; i < lines.length; i++) { if (lines[i].length > this.numCharsPerLine) { lines[i] = lines[i].substring(0, this.numCharsPerLine); } } if(lines.length < this.numLines && lines[lines.length-1].length == this.numCharsPerLine) lines[lines.length-1] += "\n" ; lines = lines.slice(0,this.numLines); // limit line number text = lines.join('\n'); //console.log(text); this.setRawValue(text) //alert(val.value) } } }] }); 值被缓存在私有数组colorTable中的System.Drawing.SystemColor类内。使用Win32 API请求,随着系统颜色的变化,将填充并更新数组的内容。

要在应用程序范围内更改系统颜色,请根据需要更改存储在KnownColorsTable中的颜色值。

然后,您还需要清除colorTableSystemBrushes类的缓存,因为画笔不会自行重新读取RBG值。

SystemPens

关于我如何完成自己的业余爱好项目的更完整的example

应在加载应用程序之前更改系统颜色,以确保控件在初始化时看到更改的值。您将需要使用Win32 API直接呈现控件的控件的其他技巧,例如using System.Drawing; using System.Reflection; namespace Example { public class SystemColorsUtility { public SystemColorsUtility() { // force init color table byte unused = SystemColors.Window.R; var colorTableField = typeof(Color).Assembly.GetType("System.Drawing.KnownColorTable") .GetField("colorTable", BindingFlags.Static | BindingFlags.NonPublic); _colorTable = (int[]) colorTableField.GetValue(null); _threadDataProperty = systemDrawingAssembly.GetType("System.Drawing.SafeNativeMethods") .GetNestedType("Gdip", BindingFlags.NonPublic) .GetProperty("ThreadData", BindingFlags.Static | BindingFlags.NonPublic); SystemBrushesKey = typeof(SystemBrushes) .GetField("SystemBrushesKey", BindingFlags.Static | BindingFlags.NonPublic) .GetValue(null); SystemPensKey = typeof(SystemPens) .GetField("SystemPensKey", BindingFlags.Static | BindingFlags.NonPublic) .GetValue(null); } public void SetColor(KnownColor knownColor, Color value) { _colorTable[(int) knownColor] = value.ToArgb(); ThreadData[SystemBrushesKey] = null; ThreadData[SystemPensKey] = null; } private int[] _colorTable; private object SystemBrushesKey { get; } private object SystemPensKey { get; } } } ListView

您可以阅读有关该here的详细信息。这是俄语的机器翻译。