带有objfpc模式下的记录的TFPGList

时间:2019-07-05 04:47:44

标签: freepascal

我想使用带有自定义记录的TFPGList。我花了很长时间才从互联网上获得所有必要的提示,以编制此小片段:

program Project1;
{$mode delphi}{$H+}
uses
  fgl;

type    
  TSomeRecord = record
    feld_1: Byte;
    class operator Equal(Left, Right : TSomeRecord) Result : Boolean;
  end;

  class operator TSomeRecord.Equal (Left, Right: TSomeRecord) Result:  Boolean;
  begin
    Result := Left.feld_1 = Right.feld_1;
  end;

type
  TypedList = TFPGList<TSomeRecord>;

var
  x : TypedList;

begin
end.    

如您所见,问题在于为记录指定Equal运算符。此外,这似乎仅在delphi模式下可行。

假定我不想以delphi模式而是以objfpc模式编写该程序:为记录指定Equal运算符的正确语法是什么?有可能吗?

我的fpc版本是3.0.4

1 个答案:

答案 0 :(得分:2)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Demo {

public class FormVisibleFalse : Form {

    private const int WM_SETFOCUS = 0x7;
    private const int SW_RESTORE = 9;
    private bool setVisible = true;

    NotifyIcon notifyIcon = new NotifyIcon();
    FormWindowState windowState = FormWindowState.Normal;
    Button btnIsVisible = new Button { Text = "IsVisible", AutoSize = true, AutoSizeMode = AutoSizeMode.GrowAndShrink };
    IntPtr mainWindowHandle = IntPtr.Zero;

    public FormVisibleFalse() {
        Text = "Form.Visible = False";
        notifyIcon.MouseClick += notifyIcon_MouseClick;
        notifyIcon.Icon = this.Icon;
        btnIsVisible.Click += btnIsVisible_Click;
        FlowLayoutPanel p = new FlowLayoutPanel { Dock = DockStyle.Fill, WrapContents = false, FlowDirection = FlowDirection.TopDown };
        p.Controls.Add(btnIsVisible);
        p.Controls.Add(new Label { Text = "After minimizing the form, click the IsVisible button.", AutoSize = true });
        Controls.Add(p);
        this.StartPosition = FormStartPosition.CenterScreen;
    }

    protected override void OnHandleCreated(EventArgs e) {
        base.OnHandleCreated(e);
        mainWindowHandle = this.Handle;
    }

    void btnIsVisible_Click(object sender, EventArgs e) {
        MessageBox.Show("Form.Visible = " + this.Visible);
    }

    void notifyIcon_MouseClick(object sender, MouseEventArgs e) {
        setVisible = false;
        this.Visible = true;
        this.WindowState = windowState;
        notifyIcon.Visible = false;
    }

    protected override void OnSizeChanged(EventArgs e) {
        base.OnSizeChanged(e);
        if (this.WindowState == FormWindowState.Minimized) {
            this.Visible = false;
            notifyIcon.Visible = true;
            setVisible = true;

            // two seconds later, restore the form.
            // Note: This is just a simple way to illustrate the problem. The actual pinvoke call
            // is made from a second instance of the process that detects if an instance is
            // already running, and restores the main window. A pipe listener could also be used to
            // pass a message telling the running instance to restore, but that's a more complicated
            // solution.
            Thread t = new Thread(() => {
                Thread.Sleep(2000);
                ShowWindow(mainWindowHandle, SW_RESTORE); // also tried SW_NORMAL and SW_SHOW
                SetForegroundWindow(mainWindowHandle);
            });
            t.IsBackground = true;
            t.Start(); // after this runs, then click the IsVisible button
        }
        else {
            windowState = this.WindowState;
        }
    }

    protected override void WndProc(ref Message m) {
        base.WndProc(ref m);

        if (m.Msg == WM_SETFOCUS && setVisible) {
            setVisible = false;
            // this.Visible = true; // <-- this fixes the problem but is there a more correct way?
            notifyIcon.Visible = false;
        }
    }

    protected override void Dispose(bool disposing) {
        base.Dispose(disposing);
        if (disposing) {
            notifyIcon.Dispose();
        }
    }

    [DllImport("user32.dll")]
    public static extern int ShowWindow(IntPtr hWnd, int cmdShow);
    [DllImport("user32.dll")]
    public static extern bool SetForegroundWindow(IntPtr hWnd);

}

}