ライトクリップ-コピー履歴を自動保存

Cocoon-inWordPress

ウインドウズには、普通のコピー、ペースト以外に、「クリップボード」というものがありますが、万能、便利なようで、意外と不便だと感じます。

WordPress=ブログを始めて、テキストに特化した、軽快なクリップボードがどうしても欲しくなり、VB.NETで「ライトクリップ」を作りました。

ウィンドウズのクリップボードとは?

Windows付属のクリップボードは、テキストエディタでも、このWordPressでも使えます。WindowsキーとVキーを押すと、

Windowsクリップボード

のようにクリップボードが現れます。どれかをクリックすれば、カーソルのある場所に貼り付けられるのです。

右肩の「・・・」をクリックすると、「ピン留めする」などのメニューも現れます。画像なども含まれているので、大変便利なものです。

軽快なクリップボードが、やはり欲しい

しかし、テキスト編集に限ってみると、貼り付けたらすぐ隠れてしまう、いちいちスクロールして探すのが面倒、などの不便があります。テキスト編集には立派すぎるのです。高級自動車も良いものかもしれませんが、自転車の代えがたい便利さもあります。

そこで、自転車、というよりむしろ、歩きのような軽い、サクサク動く、便利なクリップボード=「ライトクリップ」を作ってみました。

コピーしたテキストをリストに保存

起動すると、次のようなウインドウが開きます。コピーする度に、リストボックスにどんどん、上から追加されていきます。このリストの中から、どれか欲しいものをクリックすれば、今度は、それがクリップボードにコピーされて、編集中のテキストに貼り付けることができます。

スタートアップにショートカットをいれておいて、常駐させておくと便利です。「ああ、さっきのコピーがほしい」と思った時、いつでも取り出せます。

ウインドウは常時最前面にも、通常にも

起動直後は(↓)、ウインドウが常時最前面の状態です。

「通常化」ボタンをクリックすると、常時最前面ということではなく、通常のウインドウになります。

これ(↑)は、通常ウインドウの状態で、他のウインドウの後ろになったりもします。ここで、「最前面化」ボタンをクリックすると、

のように(↑)、また最初の常時最前面ウインドウに戻ります。

その時々で、使いやすい状態を選ぶことができます。

右の「最小化」ボタンをクリックすると、最小化され、タスクバーのアイコンだけになります。タスクバーのアイコンをクリックすれば、元に戻ります。

右肩の「×」ボタンをクリックすると、終了します。

軽いソフトなので、ショートカットをWindowsのスタートアップ・フォルダに入れておくと、パソコンを起動する度に、ライトクリップも起動します。こうして常駐させておくと、「あっ、さっきコピーしたものがまた欲しい」と思った時に、大変助かります。

リストボックス内で、右クリックメニューで、「クリア」を選択しますと、全て消えます。

コピーをする度にリストに保存

テキストをコピーすると、その度に、リストに上から追加されます。リストの限度は50までとしました。それ以上になると、自動的に下から削除します。あまり多くなると、重くなるので、50あれば十分だと、思います。

新たにコピーすると、リストの上から10項目をチェックして、同じテキストがすでにあれば、追加はしません。

リストが11個以上になって、11番目以下をクリックすると、そのテキストが最上位に追加されます。この場合も、10項目内に同じものがあれば、追加はされません。

機能を追加しました

(2022年8月)

1つは、終了時に(あるいはControl + S で)、リストを自動的に「listtext.txt」として保存し、再起動した際に、それを読み込んで以前のリストを再生するようにしました。

2つ目は、終了時に(あるいはControl + W で)、ウィンドウの位置を自動的に「winpos.txt」として保存し、再起動した際に、それを読み込んで以前のウィンドウ位置を再現するようにしました。

3つ目は、他のアプリを使っていて、ライトクリップのリストをクリックした時に、クリップボードにうまくセットされていない時がありました。確かに、セットされたことを、確認するために、クリックしたものが一番上に表示されるようにしました。

4つ目は、右クリックメニューに「1項目削除」を追加しました。分かりやすいように、「クリア」を「全クリア」に変更しました。

4つ目は、Control + ↓ でウインドウの最小化をできるようにしました。

ライトクリップのダウンロード

user32ライブラリーを使うため、フォルダごとまとめて置いておく必要があります。解凍しますと、「lightclip」という名前のフォルダになります。その中には、次のようなファイルがあります。

lightclipフォルダを適当な場所に、そのまま置いて、そのなかの lightclip.exe をダブルクリックすると、ライトクリップが起動します。「分からなくなったら.txt」は、このページへのリンクを書き込んだものです。随時更新もしますので、困った時は、ご訪問ください。

ダウンロードの際に、次のような警告が出ます。^で、継続、ダウンロードした上で、

アンチウイルスソフト(右クリックメニューでMicorsoft Definderなど)でスキャンしてから、お使い下さい。Windows PC 専用のソフトです。

VB.NET コード

コードは次のようなものです。安心していただけたら、ダウンロードして、使ってみてください。ウインドウの最前面化には、SetWindowPos を使いました。

Imports System.ComponentModel

Public Class Form1
    Private Const CHECKLINES = 5    '同じものがないか、チェックする行数
    Private Const LISTLINES = 50    '最大行数

    Private Const HWND_TOPMOST = -1
    Private Const HWND_NOTOPMOST = -2
    Private Const SWP_NOSIZE = &H1
    Private Const SWP_NOMOVE = &H2
    Private Const TEXT_FILE_NAME = "listtext.txt"
    Private Const WINDOWPOS_FILE_NAME = "winpos.txt"

    Dim lb_index = -1

    Private Declare Function SetWindowPos Lib "user32" _
    (ByVal hWnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long

    Private Sub FormPosition(Optional wndtop% = HWND_TOPMOST)
        Select Case wndtop%
            Case HWND_TOPMOST
                SetWindowPos(Me.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE + SWP_NOSIZE)
            Case HWND_NOTOPMOST
                SetWindowPos(Me.Handle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE + SWP_NOSIZE)
        End Select
    End Sub
    Private Sub CutOff(ll_num As Integer)
        Dim n, c As Integer

        c = ListBox1.Items.Count
        If c > ll_num Then
            For n = c - 1 To ll_num Step -1
                ListBox1.Items.RemoveAt(n)
            Next
        End If
    End Sub
    Private Sub WriteList()
        Dim sw As New System.IO.StreamWriter(TEXT_FILE_NAME, False) 'Falseは上書き、ファイルがなければ作ってくれる
        Dim n
        If ListBox1.Items.Count = 0 Then
            Exit Sub
        End If
        For n = 0 To ListBox1.Items.Count - 1 '
            sw.WriteLine(ListBox1.Items(n))
        Next
        sw.Close()
    End Sub
    Private Sub SetList()
        If (Not (System.IO.File.Exists(TEXT_FILE_NAME))) Then 'ファイルがなければパス
            Exit Sub
        End If

        Dim sr As New System.IO.StreamReader(TEXT_FILE_NAME)

        Do While sr.EndOfStream = False
            ListBox1.Items.Add(sr.ReadLine())
        Loop
        sr.Close()
    End Sub
    Private Sub WriteWinPos()
        If (Me.Left + Me.Top) < -100 Then 'windowsで閉じられたら書かない
            Exit Sub
        End If

        Dim sw As New System.IO.StreamWriter(WINDOWPOS_FILE_NAME, False) 'Falseは上書き、ファイルがなければ作ってくれる
        sw.WriteLine(Me.Left)
        sw.WriteLine(Me.Top)
        sw.Close()
    End Sub
    Private Sub SetWinPos()
        If (Not (System.IO.File.Exists(WINDOWPOS_FILE_NAME))) Then 'ファイルがなければパス
            Exit Sub
        End If

        Dim sr As New System.IO.StreamReader(WINDOWPOS_FILE_NAME)
        Dim l, t As Integer
        t = sr.ReadLine()
        l = sr.ReadLine()
        sr.Close()
        Me.Location = New Point(t, l)
    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        SetWinPos()
        SetList()
        FormPosition()
        Me.WindowState = FormWindowState.Minimized 'テストが終われば戻す
    End Sub
    Private Sub Form1_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
        WriteList()
        WriteWinPos()
    End Sub
    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        Dim clp As String, n, m As Integer

        clp = Clipboard.GetText()
        m = CHECKLINES
        If Len(clp) > 0 Then
            If ListBox1.Items.Count = 0 Then
                ListBox1.Items.Add(clp)
                Exit Sub
            ElseIf ListBox1.Items.Count < CHECKLINES Then
                m = ListBox1.Items.Count
            End If
            For n = 0 To m - 1 '同じものがないか、m(CHECKLINES)個チェック
                If clp = ListBox1.Items(n) Then
                    ListBox1.SetSelected(0, False)  '最新のもの以外は選択解除
                    Exit Sub
                End If
            Next
            ListBox1.Items.Insert(0, clp)   '同じものがないと、先頭に挿入する
            ListBox1.SelectedIndex = 0      '入りましたよ、と選択する
        End If
        CutOff(LISTLINES)   '最大行数を超えれば、その分を削除
    End Sub
    Private Sub ListBox1_Click(sender As Object, e As MouseEventArgs) Handles ListBox1.MouseClick
        Dim p_lbcliptext As String
        If ListBox1.SelectedItem = Nothing Then
            Exit Sub
        End If
        p_lbcliptext = ListBox1.SelectedItem
        Clipboard.SetText(p_lbcliptext) 'クリックしたものが、
        ListBox1.Items.Insert(0, p_lbcliptext)   'うまくセットできたことを確認のため、先頭に挿入する
        '先頭のCHECKLINES個になければ、リストの先頭に移動する
    End Sub
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        If Button1.Text = "最前面化" Then
            FormPosition(HWND_TOPMOST)
            Button1.Text = "通常化"
        Else
            FormPosition(HWND_NOTOPMOST)
            Button1.Text = "最前面化"
        End If
    End Sub
    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        Me.WindowState = FormWindowState.Minimized
    End Sub
    Private Sub クリアToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles クリアToolStripMenuItem.Click
        ListBox1.Items.Clear()
        Clipboard.Clear()
    End Sub
    Private Sub ListBox1_KeyDown(sender As Object, e As KeyEventArgs) Handles ListBox1.KeyDown
        'Form1_KeyDownは拾えない
        If e.KeyCode = Keys.S And e.Control Then
            WriteList()
        End If
        If e.KeyCode = Keys.W And e.Control Then
            WriteWinPos()
        End If
        If e.KeyCode = Keys.Down And e.Control Then
            Me.WindowState = FormWindowState.Minimized
        End If
    End Sub
    Private Sub 削除ToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles 削除ToolStripMenuItem.Click
        If lb_index < 0 Then Exit Sub
        ListBox1.Items.RemoveAt(lb_index)
        lb_index = -1
    End Sub
    Private Sub ListBox1_MouseDown(sender As Object, e As MouseEventArgs) Handles ListBox1.MouseDown
        If e.Button = MouseButtons.Right Then
            If ListBox1.IndexFromPoint(e.Location) <> ListBox.NoMatches Then
                lb_index = ListBox1.IndexFromPoint(e.Location) '削除ToolStripMenuItem_Click用
            End If
        End If
    End Sub
End Class

コメント