地震会商技术系统地震数据专家[DataEQ]

DatistEQ之Windows标准API

2021-03-27  本文已影响0人  了无_数据科学

2021 Q1版DatistEQ提供标准Windows API,应用程序可给DatistEQ发送一个或多个文件的路径,DatistEQ自动创建数据源节点。支持文件:.db,.db3,.sqlite,.csv,.txt,.json,.htm,.html,.xml,.eqt,.xls,.xlsx,.pdf,.doc,.docx,.e2d,grd,.dxf,.kml,.shp,.png,.jpg,.wis

发送消息

C#示例代码如下:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;

namespace ConsoleApp7
{

    public struct COPYDATASTRUCT
    {
        public IntPtr dwData; // 任意值
        public int cbData;    // 指定lpData内存区域的字节数

        [MarshalAs(UnmanagedType.LPStr)]
        //[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
        public string lpData; // 发送给目标窗口文件名称
    }
    public delegate bool Win32Callback(IntPtr hwnd, IntPtr lParam);

    class Program
    {

        const int WM_COPYDATA = 0x004A; // 固定数值,不可更改
        const int WM_USER = 0x0400;// 0x00C2;

        // 导出SendMessage函数
        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        private static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, ref COPYDATASTRUCT lParam);

        [DllImport("user32.dll")]
        public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

        [DllImport("user32.Dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool EnumChildWindows(IntPtr parentHandle, Win32Callback callback, IntPtr lParam);

        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        static extern int GetWindowTextLength(IntPtr hWnd);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
        static void Main(string[] args)
        {

            //待发送文件路径,多个文件以“|”间隔
            //支持的文件类型有.db,.db3,.sqlite,.csv,.txt,.json,.htm,.html,.xml,.eqt,.xls,.xlsx,
            //.pdf,path,.doc,.docx,.e2d,grd,.dxf,.kml,.shp,.png,.jpg,.wis
            string s =  @"C:\Users\Yao\Desktop\DSendmessage\xxx.txt";

            // 枚举进程
            var procs = Process.GetProcesses();
            foreach (Process p in procs)
            {
                //Datist为DatistEQ的进程名称
                if (!p.ProcessName.Equals("Datist")) continue;//Datist WpfApp3
         
                // 获取目标进程句柄
                var lst = GetRootWindowsOfProcess(p.Id);
                //IntPtr hWnd = p.MainWindowHandle;

                foreach (var hWnd in lst)
                { 
                    Console.WriteLine($"{p.Id} : { hWnd}");
                    // 封装消息
                    byte[] sarr = Encoding.Default.GetBytes(s);

                    COPYDATASTRUCT cds2;
                    cds2.dwData = (IntPtr)0;
                    cds2.cbData = sarr.Length + 1;
                    cds2.lpData = s;

                    // 发送消息
                    SendMessage(hWnd, WM_COPYDATA, IntPtr.Zero, ref cds2);
 
                    Console.WriteLine("SendMessage");
                }

            }

            Console.ReadKey();
        }


        static List<IntPtr> GetRootWindowsOfProcess(int pid)
        { 
            List<IntPtr> rootWindows = GetChildWindows(IntPtr.Zero);
            List<IntPtr> dsProcRootWindows = new List<IntPtr>();
            foreach (IntPtr hWnd in rootWindows)
            {
                GetWindowThreadProcessId(hWnd, out var lpdwProcessId);
                if (lpdwProcessId != pid) continue;
                var title = GetText(hWnd); 
                if (title.StartsWith("地震数据专家"))
                {
                    dsProcRootWindows.Add(hWnd);
                }
            }
            return dsProcRootWindows;
        }

        public static string GetText(IntPtr hWnd)
        {
            // Allocate correct string length first
            int length = GetWindowTextLength(hWnd);
            StringBuilder sb = new StringBuilder(length + 1);
            GetWindowText(hWnd, sb, sb.Capacity);
            return sb.ToString();
        }
        public static List<IntPtr> GetChildWindows(IntPtr parent)
        {
            List<IntPtr> result = new List<IntPtr>();
            GCHandle listHandle = GCHandle.Alloc(result);
            try
            {
                var childProc = new Win32Callback(EnumWindow);
                EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
            }
            finally
            {
                if (listHandle.IsAllocated)
                    listHandle.Free();
            }
            return result;
        }

        private static bool EnumWindow(IntPtr handle, IntPtr pointer)
        {
            GCHandle gch = GCHandle.FromIntPtr(pointer);
            List<IntPtr> list = gch.Target as List<IntPtr>;
            if (list == null)
            {
                throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
            }
            list.Add(handle);
            //  You can modify this to check to see if you want to cancel the operation, then return a null here
            return true;
        }
    }
}


delphi示例代码如下:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,StrUtils,
  Dialogs, StdCtrls,Tlhelp32;

type
  TForm1 = class(TForm)
    Button3: TButton;
    Edit1: TEdit;
    Button4: TButton;
    procedure Button3Click(Sender: TObject);
    procedure FindProcess();
    procedure Button4Click(Sender: TObject);
    function GetHWndByPID(const hPID: THandle): THandle;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button3Click(Sender: TObject);
var
  h: HWND;
  x : TStringList;
  copydata : TCopyDataStruct;
  ms : TMemoryStream; 
  lvStream:TMemoryStream;
begin
  h := FindWindow(nil,  PChar('地震数据专家(DatistEQ) - 新建流程1xxxxxx.DMS'));  // MainWindow
  x:=TStringList.Create; 
  x.add(Edit1.Text);
  
  ms := TMemoryStream.Create;
  x.SaveToStream(ms);

  lvStream := TMemoryStream.Create;
  lvStream.Write(Edit1.Text[1], Length(Edit1.Text));
  lvStream.Position := 0;

  copyData.dwData := 1;
  CopyData.lpData := ms.Memory;
  CopyData.cbData := ms.Size;
  SendMessage(h,WM_CopyData,0,integer(@CopyData));
  x.free;
  ms.free;
end;
 
procedure TForm1.FindProcess();
var
  hSnapshot: THandle;//用于获得进程列表
  lppe: TProcessEntry32;//用于查找进程
  Found: Boolean;//用于判断进程遍历是否完成
  AFileName:string;
  h: HWND;
  x : TStringList;
  copydata : TCopyDataStruct;
  ms : TMemoryStream;
begin
  AFileName:='Datist.exe';

  hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);//获得系统进程列表
  lppe.dwSize := SizeOf(TProcessEntry32);//在调用Process32First API之前,需要初始化lppe记录的大小
  Found := Process32First(hSnapshot, lppe);//将进程列表的第一个进程信息读入ppe记录中
  while Found do
  begin
    if ((UpperCase(ExtractFileName(lppe.szExeFile))=UpperCase(AFileName)) or (UpperCase(lppe.szExeFile )=UpperCase(AFileName))) then
    begin
        h := GetHWndByPID(lppe.th32ProcessID);

        x:=TStringList.Create; 
        //x.add(Edit1.Text);
        //注意字符串的长度,Delphi向C#发信息时,长度为奇数时会引起异常。
        if Length(Edit1.Text) mod 2=0 then  x.add(Edit1.Text+' ') else  x.add(Edit1.Text);
        ms := TMemoryStream.Create;
        x.SaveToStream(ms);

        copyData.dwData := 1;
        CopyData.lpData := ms.Memory;
        CopyData.cbData := ms.Size;
        SendMessage(h,WM_CopyData,0,integer(@CopyData)); //最好用PostMessage
        x.free;
        ms.free;
    end;
    Found := Process32Next(hSnapshot, lppe);//将进程列表的下一个进程信息读入lppe记录中
  end;
end;

//跟据ProcessId获取进程的窗口句柄
function TForm1.GetHWndByPID(const hPID: THandle): THandle;
type
    PEnumInfo = ^TEnumInfo;
    TEnumInfo = record
        ProcessID: DWORD;
        HWND: THandle;
    end;

    function IsMainWindow(AHandle: THandle): Boolean;
    var
        ATitle: string;
        ALen: Integer;
    begin
        Result :=(GetWindow(AHandle, GW_OWNER) = 0) and (IsWindowVisible(AHandle));
        if Result then begin
           ALen := GetWindowTextLength(AHandle) + 1;
           SetLength(ATitle, ALen);
           GetWindowText(AHandle, PChar(ATitle), ALen);
           Result:= AnsiStartsStr('地震数据专家',ATitle);  //获取主窗体
        end;
    end;{ IsMainWindow }

    function EnumWindowsProc(Wnd: DWORD; var EI: TEnumInfo): Bool; stdcall;
    var
        PID: DWORD;
    begin
        GetWindowThreadProcessID(Wnd, @PID);
        Result := (PID <> EI.ProcessID) or (not IsMainWindow(WND)) ;
        if not Result then EI.HWND := WND;
    end; { EnumWindowsProc }

    function FindMainWindow(PID: DWORD): DWORD;
    var
        EI: TEnumInfo;
    begin
        EI.ProcessID := PID;
        EI.HWND := 0;
        EnumWindows(@EnumWindowsProc, Integer(@EI));
        Result := EI.HWND;
    end; {FindMainWindow}
begin
    if hPID<>0 then
        Result:=FindMainWindow(hPID)
    else
        Result:=0;
end;{GetHWndByPID}

procedure TForm1.Button4Click(Sender: TObject);
begin
  FindProcess();
end;

end.

文件路径消息:
发送一个或多个文件路径,数据专家自动创建一个或多个节点。多个文件路径之间以“|”或换行回车为间隔。


文件路径消息

运行节点消息:
格式为“Run:节点ID”。


运行节点
上一篇下一篇

猜你喜欢

热点阅读