Archive for 3 月, 2007

用SetForegroundWindow将窗体提到最前的实现

星期四, 8 3 月, 2007

前段时间写的C#程序启动欢迎窗体实现,在运行时虽然能显示欢迎窗体,但运行后不能把主窗体提到最前。结合网上搜罗了好多资料,自己做了好几个方案来实现,最终可以解决了。

起因:
2000/XP 改变了SetForegroundWindow的执行方式,不允许随便把窗口提前,打扰用户的工作。

思路:
可以用附加本线程到最前面窗口的线程,从而欺骗windows。

实现:
原理:将显示欢迎窗体的线程作为Foreground的线程。
1. API函数的导入
public const int SW_HIDE = 0;
public const int SW_NORMAL = 1;
public const int SW_SHOWMINIMIZED = 2;
public const int SW_SHOWMAXIMIZED = 3;

[DllImport("User32.dll")]
public static extern void SetForegroundWindow(IntPtr hwnd);

[DllImport("User32.dll")]
public static extern IntPtr GetForegroundWindow();

[DllImport("User32.dll")]
public static extern int GetWindowThreadProcessId(IntPtr hwnd, IntPtr pProcId);

[DllImport("User32.dll")]
public static extern bool AttachThreadInput(int idAttach, int idAttachTo, int fAttach);

[DllImport("User32.dll")]
public static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);

2. 使用API函数实现
private static void ActivateMainInstance(IntPtr mainWindowHandle, int foreId)
{
int curId = GetWindowThreadProcessId(mainWindowHandle, IntPtr.Zero);

if (curId != foreId)
{
AttachThreadInput(foreId, curId, 1);
SetForegroundWindow(mainWindowHandle);
AttachThreadInput(foreId, curId, 0);
}
else
{
SetForegroundWindow(mainWindowHandle);
}
ShowWindowAsync(mainWindowHandle, SW_SHOWMAXIMIZED);
}

3. 调用:
private static ApplicationContext _context = null;
private static SplashScreen _splash = null;
private static MainFrame _mForm = null;

private static void OnAppIdle(object sender, EventArgs e)
{
if (_context.MainForm == null)
{
Application.Idle -= new EventHandler(OnAppIdle);

// Initialize main frame and show
_mForm.InitializeFrame(); // 花时间点
_context.MainForm = _mForm;
_context.MainForm.Show();

// Active main form
ActivateMainInstance(_mForm.Handle, _splash.ThreadId);

// Close splash screen
_splash.Close();
_splash = null;
}
}

4. Main函数中:
// Show splash screen
_splash = new SplashScreen();
_splash.Run();

// Application running
_mForm = new MainFrame();
_context = new ApplicationContext();
Application.Idle += new EventHandler(OnAppIdle);
Application.Run(_context);

5. SplashScreen的实现:
public class SplashScreen
{
private SplashForm _sForm = null;
private Thread _workThread = null;

///

/// Thread function: shows this splash form.
///

private void Show()
{
_sForm = new SplashForm();
_sForm.ShowDialog();
}

///

/// Thread id property
///

public int ThreadId
{
get
{
return _workThread.ManagedThreadId;
}
}

///

/// Runs this instance.
///

public void Run()
{
_workThread = new Thread(new ThreadStart(Show));
_workThread.Start();
}

///

/// Closes this instance.
///

public void Close()
{
if (_sForm != null)
{
_sForm.HideSplash = true;
_workThread.Join();
_workThread = null;
}
}
}

今天开始做业务了!

星期三, 7 3 月, 2007

今天领导的很多政策下来了,我要做业务了!心里又高兴又紧张,公司的政策对我还算合理吧,压力也大,但还好不是压得不能正常呼吸,我也希望自己能对自己有所突破,希望自己干得开心吧,钞票也多多就好了!

还希望大家支持我,鼓励我,希望我越做越好!

做业务时间上要灵活一些,感觉要轻松一些,我也希望下年怀孕以后也能继续干下去,为我们的小家多一份收入,看到老公辛苦的挣钱钱我的心里也不好受。嗯,老公我们共同努力,房子,车子,一切都会有的,我们会幸福永远滴!!!!

上午的会议...............

星期四, 1 3 月, 2007

        上午,老板在公司开会了,总结了公司去年的收获得失,也说了今年的任务。今年是公司的关键年,也是电子商务热闹年,公司的将来,公司的成败也在今年。

         公司的成败,关键在于今年的业绩,业绩上去了,风险什么的都来了,资金来了公司就有前途了,上海的业务今年要提高,提高的关键也要在看我,说到看我,我就好紧张,感觉压力上来了

       公司目前的“商务通”,主销产品是我和公司领导共同策划的,所以我对这个产品是最熟悉的,领导要让我去销售,希望能给公司带来一些收益,当然我也很乐意,在此一博吧!我对我们的产品还是很有信心的,希望大家都给我帮助和鼓励,我也希望走出这样的黑暗时代!加油吧

C#PropertyGrid多行编辑实现

星期四, 1 3 月, 2007

如要在PropertyGrid中显示多行编辑时需要重载UITypeEditor类并修改EditorAttribute属性。

1. 重载类MultilineTextEditor
public class MultilineTextEditor : UITypeEditor
{
private static ILog _log = LogManager.GetLogger(typeof(MultilineTextEditor));

public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.DropDown;
}

public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, IServiceProvider provider, object value)
{
try
{
IWindowsFormsEditorService svc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));

if (svc != null)
{
if (value is string)
{
TextBox box = new TextBox();

box.AcceptsReturn = true;
box.Multiline = true;
box.Height = 120;
box.BorderStyle = BorderStyle.None;
box.Text = value as string;
svc.DropDownControl(box);

return box.Text;
}
}
}
catch (Exception ex)
{
if (_log.IsErrorEnabled)
{
_log.Error("MultilineTextEditor error: " + ex.Message);
}

return value;
}

return value;
}
}

2. 增加EditorAttribute属性
[DescriptionAttribute("The item description."),
EditorAttribute(typeof(MultilineTextEditor), typeof(System.Drawing.Design.UITypeEditor))]
public string Description
{
get { return _data.Description; }
set { _data.Description = value; }
}

3. 将包含各个属性的类实例赋给PropertyGrid的SelectedObject属性,即可通过这个实现进行读写操作。

4. PropertyGrid 的部分外观特征
通过 HelpBackColor、HelpForeColor 和 HelpVisible 属性可以更改背景颜色、更改字体颜色或隐藏说明窗格。
通过 ToolbarVisible 属性可以隐藏工具栏,通过 BackColor 属性可以更改工具栏的颜色,通过 LargeButtons 属性可以显示大工具栏按钮。
使用 PropertySort 属性可以按字母顺序对属性进行排序和分类。
通过 BackColor 属性可以更改拆分器的颜色。
通过 LineColor 属性可以更改网格线和边框。

5. 部分属性的显示方式
DescriptionAttribute - 设置显示在属性下方说明帮助窗格中的属性文本。这是一种为活动属性(即具有焦点的属性)提供帮助文本的有效方法。
CategoryAttribute - 设置属性在网格中所属的类别。当您需要将属性按类别名称分组时,此特性非常有用。如果没有为属性指定类别,该属性将被分配给杂项类别。可以将此特性应用于所有属性。
BrowsableAttribute – 表示是否在网格中显示属性。此特性可用于在网格中隐藏属性。默认情况下,公共属性始终显示在网格中。
ReadOnlyAttribute – 表示属性是否为只读。此特性可用于禁止在网格中编辑属性。默认情况下,带有 get 和 set 访问函数的公共属性在网格中是可以编辑的。
DefaultValueAttribute – 表示属性的默认值。如果希望为属性提供默认值,然后确定该属性值是否与默认值相同,则可使用此特性。
DefaultPropertyAttribute – 表示类的默认属性。在网格中选择某个类时,将首先突出显示该类的默认属性。