2004年09月08日

预算方式更改为“盈亏计算”的方式。

优点主要体现在:

全部是资金数据,非资金数据输入到其他窗口。

可以与财务系统接口。

可以随时查看预算与实际差别。

合同终结后可以查看预核算比较。

分类更明晰,区分海运费、采购成本等等成本费用的明细情况。

 

对应

               -数量(为出口商品的数量)

销售货价-出口金额

采购货价-进货成本

 

 

2004年09月01日

 

 

       AddIn树是由一个提供其余应用程序所用功能的接口定义的。为了总览该结构所提供的功能,我们将介绍IAddInTree接口,它位于src\Main\Core\AddIns\IAddInTree.cs

       public interface IAddInTree

       {

              /// <summary>

              /// Returns the default condition factory. ICondition objects

              /// are created only with this factory during the tree

              /// construction process.

              /// </summary>

              ConditionFactory ConditionFactory {

                     get;

              }

 

              /// <summary>

              /// Returns the default codon factory. ICodon objects

              /// are created only with this factory during the tree

              /// construction process.

              /// </summary>

              CodonFactory CodonFactory {

                     get;

              }

 

              /// <summary>

              /// Returns a collection of all loaded add-ins.

              /// </summary>

              AddInCollection AddIns {

                     get;

              }

             

              /// <summary>

              /// Returns a TreeNode corresponding to <paramref name=”path”/>.

              /// </summary>

              /// <param name=”path”>

              /// The path.

              /// </param>

              /// <exception cref=”TreePathNotFoundException”>

              /// When the path <paramref name=”path”/> does not point to a codon

              /// in the tree.

              /// </exception>

              IAddInTreeNode GetTreeNode(string path);

             

              /// <summary>

              /// Inserts an AddIn into the AddInTree.

              /// </summary>

              void InsertAddIn(AddIn addIn);

 

              /// <summary>

              /// Removes an AddIn from the AddInTree.

              /// </summary>

              void RemoveAddIn(AddIn addIn);

             

              /// <summary>

              /// This method does load all codons and conditions in the given assembly.

              /// It will create builders for them which could be used by the factories

              /// to create the codon and condition objects.

              /// </summary>

              Assembly LoadAssembly(string assemblyFile);

       }

 

       首先,AddIn树包含ConditionFactorCodonFactory对象,这些工厂创建了AddIn树节点内容。下一个属性是AddIn属性。

       AddIns属性之后是GetTreeNode方法,该方法非常重要,是使用AddIn树插件唯一所需要的方法。其他方法和属性当前只内部的用于核心程序集。

       InserAddInRemoveAddIn方法可能用于IDE中实现插件管理器,但当前并为使用。了解IAddInTree接口的重要方法之后,让我们看一下插件文件的定义。

2004年08月30日

 

 

       与其它设计方法相比,AddIn树有不少优点:

l         可以通过其他插件扩展以有插件。但这样做的主要问题是:其他插件执行动作时必须通知以有的插件。

l         在者,包含可执行代码的assembly文件不必驻留在一个目录中。开发人员可以将它们存储在任何位置,插件系统将管理文件加载。这就使实现插件的“复制和删除”部署变得非常容易。只须将包含XML定义和所需要程序集的插件文件夹复制到SharpDevelop AddIn 文件夹,就奏效了。删除目录,插件就会被取出!注意,.NET标准将把所有程序集都放在一个bin目录中。

l         使用上述方法时,查检不必实现自己的插件结构,因为所有插件都基于一个系统—AddIn数。通过一个窄接口,我们可以定义任何功能

 

src\Main\StartUp\SharpDevelopMain.cs文件中,有一个运行所有动作的方法:

       public class SharpDevelopMain

       {

              static string[] commandLineArgs = null;

             

              public static string[] CommandLineArgs {

                     get {

                            return commandLineArgs;

                     }

              }

             

              static void ShowErrorBox(object sender, ThreadExceptionEventArgs eargs)

              {

                     DialogResult result = new ExceptionBox(eargs.Exception).ShowDialog();

 

                     switch (result) {

                            case DialogResult.Ignore:

                                   break;

                            case DialogResult.Abort:

                                   Application.Exit();

                                   break;

                            case DialogResult.Yes:

                                   break;

                     }

              }

             

              /// <summary>

              /// Starts the core of SharpDevelop.

              /// </summary>

              [STAThread()]

              public static void Main(string[] args)

              {

                     commandLineArgs = args;

                     bool noLogo = false;

                    

                     SplashScreenForm.SetCommandLineArgs(args);

                    

                     foreach (string parameter in SplashScreenForm.GetParameterList()) {

                            switch (parameter.ToUpper()) {

                                   case “NOLOGO”:

                                          noLogo = true;

                                          break;

                            }

                     }

                    

                     if (!noLogo) {

                            SplashScreenForm.SplashScreen.Show();

                     }

                     Application.ThreadException += new ThreadExceptionEventHandler(ShowErrorBox);

                    

                     bool ignoreDefaultPath = false;

                     string [] addInDirs = ICSharpCode.SharpDevelop.AddInSettingsHandler.GetAddInDirectories(out ignoreDefaultPath);

                     AddInTreeSingleton.SetAddInDirectories(addInDirs, ignoreDefaultPath);

                    

                     ArrayList commands = null;

                     try {

                            ServiceManager.Services.AddService(new MessageService());

                            ServiceManager.Services.AddService(new ResourceService());

                            ServiceManager.Services.AddService(new IconService());

                            ServiceManager.Services.InitializeServicesSubsystem(“/Workspace/Services”);

                    

                            commands = AddInTreeSingleton.AddInTree.GetTreeNode(“/Workspace/Autostart”).BuildChildItems(null);

                            for (int i = 0; i < commands.Count – 1; ++i) {

                                   ((ICommand)commands[i]).Run();

                            }

                     } catch (XmlException e) {

                            MessageBox.Show(“Could not load XML :” + Environment.NewLine + e.Message);

                            return;

                     } catch (Exception e) {

                            MessageBox.Show(“Loading error, please reinstall :”  + Environment.NewLine + e.ToString());

                            return;

                     } finally {

                            if (SplashScreenForm.SplashScreen != null) {

                                   SplashScreenForm.SplashScreen.Close();

                            }

                     }

                    

                     try {

                            // run the last autostart command, this must be the workbench starting command

                            if (commands.Count > 0) {

                                   ((ICommand)commands[commands.Count - 1]).Run();

                            }

                     } finally {

                            // unloading services

                            ServiceManager.Services.UnloadAllServices();

                     }

              }

       }

 

首先,Main方法初始化启动画面,这不太重要,但当我们作实际工作时,如生成AddIn树,用户至少会看到一些内容。

try…catch块非常重要。为AddIn树创建一个调用,以获取数节点,然后他会从该节点生成所有子项目。

此后,for语句将这些生成的子项目强制转换为ICommand 接口,并调用 Run 方法最后一个除外。

try…catch快之后,启动最后一个命令。我们将分别启动,以确保启动最后一个命令时关闭启动画面。最后一个命令激活IDE的工作台窗体,并运行消息循环。

按照SharpDevelop不再核心嵌入任何GUI层,这就是为其他工具箱的进一步使用提供了良好的扩展性。在应用程序实际需要时才会实现GUI层。

只需要在树中放入其他Run命令,就可以在树创建一个完全不同的应用程序。该引用程序可受益AddIn树。

返回最后一个Run命令时,就认为应用程序消息循环已经结束,于是通过服务卸载进行清理。

                                                                                                                 
    1、基本语法
   
    C#是一个块结构语言,所有的语句都是代码块的一部分。这些块用花括号来界定(“{”“}”),可以包含任意多行语句,或者根本不包含语句。
   
    {
     <code line1, statement 1>;
     <code line2, statement 2>
      <code line3, statement 3>;
    }
   
    其中<code line X, statement Y>部分并不是真正的C#代码,而是用这个文本作为占位符。
   
    注释语句:
     /* And so ……
     
     …… is this!*/
     
    或者
   
    //This is a different sort of comment.
   
    2、变量
   
    C#声明变量的语法:
    <type> <name>;
   
    变量类型:
    sbyte byte short ushort int uint long ulong float double decimal char bool string
   
    3、变量的命名
   
    变量名的第一个字符必须是字母、下划线或@。
    其后的字符可以是字母、下划线或者数字。
   
    4、名称空间
   
        他们是.net中提供应用程序代码容器的方式,这样,代码及其内容就可以唯一地标识了。名称空间也是用作.NET Framework 中给项目分类的一种方式。
    在默认的情况下,C#代码包含在全局命名空间中。可以使用namespace关键字为花括号中的代码块显示定义名称空间。如果在该名称空间代码的外部使
    用名称空间中的名称,就必须写出该名称空间的限定名称。
      基本上如果一个名称空间的代码需要使用的另一个名称空间中定义的名称,就必须包含对该名称空间的引用。限定名称在不同的名称空间级别之间使用
    字符”.”。
   
    例如:
   
     namespace LevelOne
     
     {
      //code
     }
     
    这段代码定义了一个名称空间LevelOne。
   

 
作者:Eric

本文介绍SharpDevelop的基础结构。与大多数应用程序相同,SharpDevelop的核心是可执行的;又与大多数应用程序不同,他只是提供了包含其它主要任务(加载和生成AddIn树)在内的几个基本服务。 Add-ins也成为Plug-ins,这里我们还是用Add-ins这个术语。

本文将介绍AddIn树的结构和实现,并讲述AddIn的对象创建机制。还将介绍SharpDevelop是如何管理属性持久性的。

核心基础结构与其余代码是相分离的,您可以在scr\SharpDevelop\Core目录下找到它。全部插件系统位于子文件夹AddIns下的该文件夹中。

1、  AddIn

AddIn树是一个简单的树数据结构。SharpDevelop的每一个实例只有一个AddIn树,所以我们通过singleton设计模式来实现他。

XML文件和XML引用的DLL集定义了一个插件。DLL提供了代码,XML定义了将其插入到AddIn树的方式和位置。

AddIn树是一种“将他们全部邦定的树”,插件是AddIn树的节点,路经的作用是构造树,因此不是真正的节点。IDE根据这些节点的定义内容更改行为。节点的路经结构好像是一个文件系统,如果访问SubNode2,必须将位置指定为/Path1/SubPat1/Node1/SubNode2。这里,Node1似乎是一个路径(以后将介绍路径和节点的区别)。可以说,节点是包含行为定义的路径。

定义特定路径的插件也着手定义可插入到旗下的节点的接口,如图:

 

    在选项面板左侧,我们可以从树试图中看到AddIn树节点。文件夹表示空节点,其他为包含文件夹图标的树树突节点是包含面板的节点。要添加新面板,插件必须将正确节点插入到路径,对话框将显示他们。在SharpDevelop中,所有可见元素都有节点定义;大多数不可见元素,如文本编辑器中的键盘命令cursor keys,在插件树中也被作为节点实现。

2004年08月26日

商品属性在设置的时候不能挑上可追加,如果加入的话在商品中显示不出来。需要在商品中选择后在挑上。

 

另外款式号使用商品属性管理(测试)

2004年08月24日

        国内采购(包括面料辅料成品等)如果选择直掉方式,则执行的时候会自动生成入库回单,此入库回单需要货票对应。

实现方式,入库通知中,发货方式选择直掉,商品的仓库选择直掉。

系统需要在系统选项4中选择自动生成的入库回单为执行还是准备状态。

2004年08月22日

 

 

 

 

  许多软件都有自动关机功能,特别是在长时间下载的时候,这个功能可是使你不用以守候在计算机前面,而电脑却能按照您事先的设定自动关闭。现在我们用visual C#来编写一个多功能的关机程序。该程序具有:定时关机、倒计时关机、关机提醒、系统信息获取等四项功能, 可设定关机时间精确到秒。并且让你很快掌握Visual C#中对API的操作程序。


  一. 设计关闭Windows窗体

  1. 界面的设计

  新建一个标准工程,向工程中增加一个Windows窗体并向窗体中添加如下控件,并分别设置其属性:

控件名 类别 Text 控件名 类别 Text
CheckBox1 CheckBox 自动关机 GroupBox1 GroupBox 当前系统时间
CheckBox1 CheckBox 倒计时执行操作 GroupBox2 GroupBox 设定时间
CheckBox1 CheckBox 定时报警 TxtTime TextBox  
ButCancle Button 取消 SetupTime DateTimePicker  
ButReOpen Button 重新启动 SetupDate DateTimePicker  
ButClose Button 关机 Timer1 Timer 100
ButSysInto Button 系统信息 ButReLogin Button 注消

  Windows窗体界面:

  将窗体属性中的caption设置为”关闭windows”,名称设置为”frmmain”。

  2. 在窗体类中引用API函数

  API函数是构筑Windows应用程序的基石,是Windows编程的必备利器。每一种Windows应用程序开发工具都提供了间接或直接调用了Windows API函数的方法,或者是调用Windows API函数的接口,也就是说具备调用动态连接库的能力。Visual C#和其它开发工具一样也能够调用动态链接库的API函数。

  在Visual C#中调用API的基本过程:

  首先,在调用API之前,你必须先导入System.Runtime.InteropServices这个名称空间。该名称空间包含了在Visual C#中调用API的一些必要集合,具体的方法如下:

  using System.Runtime.InteropServices ;
  using System.Text ;

  在导入了名称空间后,我们要声明在程序中所要用到的API函数。我们的程序主要是获取系统的相关信息,所以用到的API函数都是返回系统信息的。先给出在Visual C#中声明API的方法:

[ DllImport("user32") ]
public static extern long SetWindowPos(long hwnd , long hWndInsertAfter, long X , long y , long cx, long cy, long wFlagslong) ;

  其中,”DllImport”属性用来从不可控代码中调用一个方法,它指定了DLL的位置,该DLL中包含调用的外部方法;”kernel32″设定了类库名;”public”指明函数的访问类型为公有的;”static”修饰符声明一个静态元素,而该元素属于类型本身而不是指定的对象;”extern”表示该方法将在工程外部执行,同时使用DllImport导入的方法必须使用”extern”修饰符;最后GetWindowsDirectory函数包含了两个参数,一个为StringBuilder类型的,另一个为int类型的,该方法返回的内容存在于StringBuilder类型的参数中。同时,因为我们在这里使用到了StringBuilder类,所以在程序的开始处,我们还得添加System.Text这个名称空间,方法同上。

  声明其它的在程序中所要用到的API函数:

[ DllImport("user32") ]
public static extern long ExitWindowsEx(long uFlags, long dwReserved ) ;
[ DllImport("shell32") ]
public static extern long ShellAbout(long uFlags, long dwReserved ) ;

  3. 增加窗体类的变量

long dwReserved ;
const int SHUTDOWN = 1 ;
const int REBOOT = 2 ;
const int LOGOFF = 0 ;
long sh ;
int counter , n ;

  4. 编写窗体类的方法

  在窗体的Load(事件过程中编写如下代码:

private void frmmain1_Load(object sender, System.EventArgs e )
{
file://用系统时间初始化组件
Time.Text = System.DateTime.Today.ToShortDateString( ) + ” “+ System.DateTime.Today.ToLongTimeString( ) ;
}

  在组件Timer1的OnTimer事件过程中编写如下代码:

/ / 在组件Timer1的OnTimer事件过程中编写如下代码:
private void Timer1_Timer(object sender, System.EventArgs e )
{
file://接收当前日期和时间,用于即时显示
string CurrDate=System.DateTime.Today.ToShortDateString( ) ;
string CurrTime=System.DateTime.Today.ToShortTimeString( ) ;
file://随时检测设定的关机日期和时间是否有效
if( this.CheckBox1.Checked == true )
{
if(CurrDate== SetupDate.ToString( ) && CurrTime==SetupTime.ToString( ) )
ColseComputer( ) ;
}
}
private void ColseComputer( )
{ sh = ExitWindowsEx(SHUTDOWN, dwReserved) ; }
private void button1_Click(object sender, System.EventArgs e )
{
Form2 frm=new Form2( ) ;
frm.Show( ) ;
}
private void ButReOpen_Click(object sender, System.EventArgs e )
{ sh = ExitWindowsEx(REBOOT, dwReserved) ; }
private void ButReLogin_Click(object sender, System.EventArgs e )
{ sh = ExitWindowsEx(LOGOFF, dwReserved) ; }
private void ButCancle_Click(object sender, System.EventArgs e )
{ this.Close( ) ; }
private void ButClose_Click_1(object sender, System.EventArgs e )
{ sh = ExitWindowsEx(REBOOT, dwReserved) ; }

  二. 设计获取系统信息的Windows窗体

  1. 界面的设计

  向工程中增加一个Windows窗体并向窗体中添加如下控件:

  2. 在窗体类中引用API函数

using System.Runtime.InteropServices ;
using System.Text ;
[ DllImport("kernel32") ]
public static extern void GetWindowsDirectory(StringBuilder WinDir,int count) ;
[ DllImport("kernel32") ]
public static extern void GetSystemDirectory(StringBuilder SysDir,int count) ;
[ DllImport("kernel32") ]
public static extern void GetSystemInfo(ref CPU_INFO cpuinfo) ;
[ DllImport("kernel32") ]
public static extern void GlobalMemoryStatus(ref MEMORY_INFO meminfo) ;
[ DllImport("kernel32") ]
public static extern void GetSystemTime(ref SYSTEMTIME_INFO stinfo) ;

  以上几个API的作用分别是获取系统路径,获得CPU相关信息,获得内存的相关信息,获得系统时间等。

  3. 定义以下各结构

  在声明完所有的API函数后,我们发现后三个函数分别用到了CPU_INFO、MEMORY_INFO、SYSTEMTIME_INFO等结构,这些结构并非是.Net内部的,它们从何而来?其实,我们在用到以上API调用时均需用到以上结构,我们将函数调用获得的信息存放在以上的结构体中,最后返回给程序输出。这些结构体比较复杂,但是如果开发者能够熟练运用,那么整个API世界将尽在开发者的掌握之中。以下就是上述结构体的声明:

//定义CPU的信息结构
[StructLayout(LayoutKind.Sequential) ]
public struct CPU_INFO
{
public uint dwOemId ;
public uint dwPageSize ;
public uint lpMinimumApplicationAddress ;
public uint lpMaximumApplicationAddress ;
public uint dwActiveProcessorMask ;
public uint dwNumberOfProcessors ;
public uint dwProcessorType ;
public uint dwAllocationGranularity ;
public uint dwProcessorLevel ;
public uint dwProcessorRevision ;
}

file://定义内存的信息结构
[StructLayout(LayoutKind.Sequential) ]
public struct MEMORY_INFO
{
public uint dwLength ;
public uint dwMemoryLoad ;
public uint dwTotalPhys ;
public uint dwAvailPhys ;
public uint dwTotalPageFile ;
public uint dwAvailPageFile ;
public uint dwTotalVirtual ;
public uint dwAvailVirtual ;
}

file://定义系统时间的信息结构
[StructLayout(LayoutKind.Sequential) ]
public struct SYSTEMTIME_INFO
{
public ushort wYear ;
public ushort wMonth ;
public ushort wDayOfWeek ;
public ushort wDay ;
public ushort wHour ;
public ushort wMinute ;
public ushort wSecond ;
public ushort wMilliseconds ;
}

  5. 编写窗体类的方法

private void button1_Click(object sender, System.EventArgs e )
{
file://调用GetWindowsDirectory和GetSystemDirectory函数分别取得Windows路径和系统路径
const int nChars = 128 ;
StringBuilder Buff = new StringBuilder(nChars) ;
GetWindowsDirectory(Buff,nChars) ;
WindowsDirectory.Text = “Windows路径:”+Buff.ToString( ) ;
GetSystemDirectory(Buff,nChars) ;
SystemDirectory.Text = ” 系统路径:”+Buff.ToString( ) ;

file://调用GetSystemInfo函数获取CPU的相关信息
CPU_INFO CpuInfo ;
CpuInfo = new CPU_INFO( ) ;
GetSystemInfo(ref CpuInfo) ;
NumberOfProcessors.Text = “本计算机中有”+CpuInfo.dwNumberOfProcessors.ToString( ) +”个CPU”;
ProcessorType.Text = “CPU的类型为”+CpuInfo.dwProcessorType.ToString( ) ;
ProcessorLevel.Text = “CPU等级为”+CpuInfo.dwProcessorLevel.ToString( ) ;
OemId.Text = “CPU的OEM ID为”+CpuInfo.dwOemId.ToString( ) ;
PageSize.Text = “CPU中的页面大小为”+CpuInfo.dwPageSize.ToString( ) ;

file://调用GlobalMemoryStatus函数获取内存的相关信息
MEMORY_INFO MemInfo ;
MemInfo = new MEMORY_INFO( ) ;
GlobalMemoryStatus(ref MemInfo) ;
MemoryLoad.Text = MemInfo.dwMemoryLoad.ToString( ) +”%的内存正在使用” ;
TotalPhys.Text = “物理内存共有”+MemInfo.dwTotalPhys.ToString( ) +”字节” ;
AvailPhys.Text = “可使用的物理内存有”+MemInfo.dwAvailPhys.ToString( ) +”字节” ;
TotalPageFile.Text = “交换文件总大小为”+MemInfo.dwTotalPageFile.ToString( ) +”字节” ;
AvailPageFile.Text = “尚可交换文件大小为”+MemInfo.dwAvailPageFile.ToString( ) +”字节” ;
TotalVirtual.Text = “总虚拟内存有”+MemInfo.dwTotalVirtual.ToString( ) +”字节” ;
AvailVirtual.Text = “未用虚拟内存有”+MemInfo.dwAvailVirtual.ToString( ) +”字节” ;

file://调用GetSystemTime函数获取系统时间信息
SYSTEMTIME_INFO StInfo ;
StInfo = new SYSTEMTIME_INFO( ) ;
GetSystemTime(ref StInfo) ;
Date.Text = StInfo.wYear.ToString( ) +”年”+StInfo.wMonth.ToString( ) +”月”+StInfo.wDay.ToString( ) +”日” ;
Time.Text = (StInfo.wHour+8).ToString( ) +”点”+StInfo.wMinute.ToString( ) +”分”+StInfo.wSecond.ToString( ) +”秒” ;
}

  三. 结束语。

  上面介绍了Visual C#开发多功能关机程序的整个过程,该程序有一定的实用价值。通过本文的学习,我相信稍有API使用基础的开发者可以马上触类旁通,很快掌握Visual C#中对API的操作。上面给出的实例仅仅是一个简单的程序,不过有兴趣的读者可以进一步完善其功能,做出更完美的系统应用程序。

首先建立两个C#应用程序项目。

  第一个项目包含一个Windows Form(Form1),在Form1上有一个Button和一个TextBox。

  第二个项目包含一个Windows Form(Form1),在Form1上有两个Button,分别用来测试第一个应用程序中Button的Click事件和修改第一个应用程序中TextBox的值。

  第一个应用程序中Form的代码如下:




  using System;
  using System.Drawing;
  using System.Collections;
  using System.ComponentModel;
  using System.Windows.Forms;

  public class Form1 : System.Windows.Forms.Form {
  private System.Windows.Forms.Button button1;
  private System.Windows.Forms.TextBox textBox1;

  private System.ComponentModel.Container components = null;

  [STAThread]
  static void Main() {
  Application.Run(new Form1());
  }

  public Form1()
  {
  InitializeComponent();
  }
  protected override void Dispose( bool disposing )
  {
  if( disposing )
  {
  if(components != null)
  {
  components.Dispose();
  }
  }
  base.Dispose( disposing );
  }

  #region Windows 窗体设计器生成的代码
  private void InitializeComponent()
  {
  this.button1 = new System.Windows.Forms.Button();
  this.textBox1 = new System.Windows.Forms.TextBox();
  this.SuspendLayout();
  //

  // button1
  //
  this.button1.Location = new System.Drawing.Point(32, 24);
  this.button1.Name = “button1″;
  this.button1.TabIndex = 0;
  this.button1.Text = “button1″;
  this.button1.Click += new System.EventHandler(this.button1_Click);
  //
  // textBox1
  //
  this.textBox1.Location = new System.Drawing.Point(32, 64);
  this.textBox1.Name = “textBox1″;
  this.textBox1.TabIndex = 1;
  this.textBox1.Text = “textBox1″;
  //
  // Form1
  //
  this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
  this.ClientSize = new System.Drawing.Size(292, 266);
  this.Controls.Add(this.textBox1);
  this.Controls.Add(this.button1);
  this.Name = “Form1″;
  this.Text = “Form1″; 
  this.ResumeLayout(false);

  }
  #endregion

  private void button1_Click(object sender, System.EventArgs e) {
  MessageBox.Show(“This is button1 click!”);
  }
  }

  第二个应用程序中Form的代码如下:

  using System;
  using System.Text;
  using System.Drawing;
  using System.Collections;
  using System.ComponentModel;
  using System.Windows.Forms;
  using System.Runtime.InteropServices;

  public class TestForm1 : System.Windows.Forms.Form {
  private System.Windows.Forms.Button button1;
  private System.Windows.Forms.Button button2;

  private System.ComponentModel.Container components = null;

 

  [STAThread]
  static void Main() {
  Application.Run(new TestForm1());
  }

  public TestForm1()
  {
  InitializeComponent();
  }
  protected override void Dispose( bool disposing )
  {
  if( disposing )
  {
  if(components != null)
  {
  components.Dispose();
  }
  }
  base.Dispose( disposing );
  }

  #region Windows 窗体设计器生成的代码
  private void InitializeComponent()
  {
  this.button1 = new System.Windows.Forms.Button();
  this.button2 = new System.Windows.Forms.Button();
  this.SuspendLayout();
  //
  // button1
  //
  this.button1.Location = new System.Drawing.Point(32, 24);
  this.button1.Name = “button1″;
  this.button1.TabIndex = 0;
  this.button1.Text = “button1″;
  this.button1.Click += new System.EventHandler(this.button1_Click);
  //
  // button2
  //
  this.button2.Location = new System.Drawing.Point(32, 64);
  this.button2.Name = “button2″;
  this.button2.TabIndex = 0;
  this.button2.Text = “button2″;
  this.button2.Click += new System.EventHandler(this.button2_Click);
  //
  // TestForm1
  //
  this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
  this.ClientSize = new System.Drawing.Size(292, 266);


  this.Controls.Add(this.button1);
  this.Controls.Add(this.button2); 
  this.Name = “TestForm1″;
  this.Text = “TestForm1″; 
  this.ResumeLayout(false);

  }
  #endregion

  private void button1_Click(object sender, System.EventArgs e) {
  IntPtr hwnd_win ;  
  IntPtr hwnd_button ;

  hwnd_win = FindWindow(“WindowsForms10.Window.8.app3″,”Form1″);
  hwnd_button = FindWindowEx(hwnd_win ,new IntPtr(0) ,”WindowsForms10.BUTTON.app3″,”button1″); 

  const int BM_CLICK = 0×00F5;
  Message msg = Message.Create(hwnd_button ,BM_CLICK ,new IntPtr(0),new IntPtr(0));
  PostMessage(msg.HWnd ,msg.Msg ,msg.WParam ,msg.LParam);
  }
  private void button2_Click(object sender, System.EventArgs e) {
  const int WM_CHAR = 0×0102;
  IntPtr hwnd_win ;
  IntPtr hwnd_textbox ;

  hwnd_win = FindWindow(“WindowsForms10.Window.8.app3″,”Form1″);  
  hwnd_textbox = FindWindowEx(hwnd_win ,new IntPtr(0) ,”WindowsForms10.EDIT.app3″,”textBox1″);    
  
  string strtext = “测试aaa”;
  UnicodeEncoding encode = new UnicodeEncoding();
  char[] chars = encode.GetChars(encode.GetBytes(strtext));
  Message msg ;
  foreach (char c in chars ) {
  msg = Message.Create(hwnd_textbox ,WM_CHAR ,new IntPtr(c),new IntPtr(0));
  PostMessage(msg.HWnd ,msg.Msg ,msg.WParam ,msg.LParam);
  }
  }

  [DllImport("user32.dll")]
  public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
  
  [DllImport("user32.dll")]
  public static extern IntPtr FindWindowEx(IntPtr hwndParent,IntPtr hwndChildAfter,string lpszClass,string lpszWindow);

  [DllImport("user32.dll",CharSet=CharSet.Unicode)] 
  public static extern IntPtr PostMessage(IntPtr hwnd,int wMsg,IntPtr wParam,IntPtr lParam);
  }

  以上代码可以在VS.NET中编译运行,也可以使用csc.exe编译,如使用一下命令行:

  F:>csc.exe Form1.cs
  F:>csc.exe TestForm1.cs

  编译后生成两个.exe文件。

  首先运行第一个程序,显示Form1窗体,然后运行第二个程序,显示TestForm1窗体。

  在TestForm1窗体上点击button1按钮(向Form1窗体上的button1发送消息)此时显示对话框提示“This is button1 click!”。

  在TestForm1窗体上点击button2按钮(向Form1窗体上的textBox1发送消息)此时在Form1上的textBox1上显示“测试aaa”。

 

 

有人问到以下问题:
在MDI中运行多个FORM1,FORM2,FORM3,如果在FORM2打开的状态下再次点击打开FORM2的菜单,如何控制不再打开一个新的FORM2,而是激活已经打开的FORM2.

如果窗口在Show后不再改变标题(大多数情况如此),可以通过判断窗口标题来实现,建立一个struct,包括一个获取MDI父窗口是否有窗口标题为指定字符串的子窗口的方法ExistWin和至少一个获取窗口标题的方法WinCaption,
代码如下:


在子窗口的构造函数中写入如下代码

this.Text = ChildWinManagement.WinCaption(…)

在父窗口中打开子窗口:

string caption = ChildWinManagement.WinCaption(…)

if(! ChildWinManagement.ExistWin(this,caption))
{
 //打开子窗口
}

2004年5月24日 7:52