こじんてきメモ

趣味とかを色々簡単に...(╹◡╹)

VBA フォームの色を透明にする

WindowsAPIを使うことで、フォーム内の特定の色を透過させることができる。

①まずは
・FindWindowA
・GetWIndowLongA
・SetWindowLongA
を使って、透過するウィンドウのIDをLONG型で取得する。

②次に、取得したウィンドウにSetLayeredWindowAttributesを使って、アルファ値(透過度)を掛け合わせたウィンドウにする。

これだけで透過できる。

Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long

Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

Private Declare PtrSafe Function SetLayeredWindowAttributes Lib "user32" (ByVal hWnd As Long, ByVal crey As Byte, ByVal bAlpha As Byte, ByVal dwFlags As Long) As Long
 
Private Const GWL_EXSTYLE = (-20)
Private Const WS_EX_LAYERED = &H80000
'SetLayeredWindowAttributes用
Private Const LWA_ALPHA = &H2&
Private Const LWA_COLORKEY = &H1&

Public hWnd As Long
Private Sub CommandButton1_Click()
    hWnd = FindWindow("ThunderDFrame", Me.Caption)
    
    Call SetWindowLong(Me.hWnd, GWL_EXSTYLE, GetWindowLong(Me.hWnd, GWL_EXSTYLE) Or WS_EX_LAYERED)
    Call SetLayeredWindowAttributes(Me.hWnd, 0, 100, LWA_COLORKEY)

End Sub
SetLayeredWindowAttributes(hwnd, crKey, bAlpha, dwFlags)

SetLayeredWindowAttributesが、解説サイトをみてもいまいちわからなかったので仕様を見てみた。
docs.microsoft.com

dwFlagsの値で以下のように変わるようだ。

LWA_ALPHA ウィンドウ全体が透過する
LWA_COLORKEY crKeyで指定した色で透過する。

※crKeyはDWORD型らしい。


以下はフォームを黒くして、黒で透過した場合のもの。壁紙も黒なのでちょっとわかりにくいが、アイコンが透過して見えているのがわかると思う。「フォーム内の特定の色」なので、基本的にフォーム上にあるボタンやラベルも透過する。
f:id:hmmr:20200509104117p:plain
f:id:hmmr:20200509104202p:plain

しかし、WMPコントロールの中までは透過してくれなかった。

以下は自分用です。
docs.microsoft.com
docs.microsoft.com
docs.microsoft.com

メモ帳C# Windowsフォームアプリのスケルトンコード

まずはFormクラスを継承したGameクラスを作成し、WindowsFormを表示させる。

using System;
using System.Windows.Forms;

class Game:Form
{
	static void Main()
	{
	Application.Run( new Game());
	}
}

次にタイトルとサイズを変更してみる。

FormクラスのOnLoadメソッドを使うと、「フォームが初めて表示される直前に発生」する「load」イベントが発生するので、ここに書いてみる。

using System;
using System.Drawing;
using System.Windows.Forms;

class Game:System.Windows.Forms.Form
{
	protected override void OnLoad(EventArgs e )
	 {
	ClientSize = new Size(1280,720);
	Text="Game";
	 }
	static void Main()
	{
	Application.Run( new Game());
	}
}

VB.Netで端末名を変更する【殴り書き】

環境:Visual Basic 2012

・端末名は2つある

今回知ったのですが、いわゆる「端末名」には2つある。
・Net BIOS
TCP/IPのコンピュータ名

COMPUTERNAMEとHOSTNAMEの違い

VB.NETでの端末名の変更

VB.Netで端末名を変更することができなさそうなので、WindowsAPIを使用する方法をとった。その際、「SetComputerName」を見つけたが、これは実は「NET BIOS」名しか変更してくれない。TCP/IPのホスト名を変更するためには「SetComputerNameEx」を使用する必要があった。
※このために、なぜホスト名が変わらないのか少し悩んだ。

・記述方法

'宣言
Declare Auto Function SetComputerNameEx Lib "kernel32.dll" (Byval NameType As Integer, Byval lpBuffer As String) As Integer
'関数を作る
Public Function SetCompName(s as String) As String
   Dim NameType As Long
   NameType = 5 '「NET BIOS」と「ホスト名」を変更する場合「ComputerNamePhysicalDnsHostname」としたいので「5」にする。
   Call SetComputerNameEx(NameType,s)
End Function

※列挙型「COMPUTER_NAME_FORMAT」
ComputerNameNetBIOS→0
ComputerNameDnsHostname→1
ComputerNameDnsDomain→2
ComputerNameDnsFullyQualified→3
ComputerNamePhysicalNetBIOS→4
ComputerNamePhysicalDnsHostname→5
ComputerNamePhysicalDnsDomain→6
ComputerNamePhysicalDnsFullyQualified→7

バッチとタスクスケジューラでなるべく簡単にフルバックアップを取得する(後編)

この記事は、Windows標準装備のバッチ処理とタスクスケジューラを用いて、簡易的だけど本格的(?)にバックアップを取得する手順を書いています。導入は以下の記事になりますので、軽くのぞいてみてください。


hmmr.hateblo.jp



この記事は↓の記事の後編になります。前編をみていない方は前編をのぞいて見てください。
hmmr.hateblo.jp

ここから手順になります。

2.タスクスケジューラへのタスク登録

1.コントロールパネルを開いて、小さいアイコンをクリック。
f:id:hmmr:20200310214248j:plain

2.管理ツール→タスクスケジューラ を開きます。
f:id:hmmr:20200310214317j:plain
f:id:hmmr:20200310214328j:plain

3.基本タスクの作成をクリック
f:id:hmmr:20200310214454j:plain

4.「名前」→「日次バックアップ」をいれて次へをクリック
f:id:hmmr:20200310214535j:plain

5.「毎日」をチェックして「次へ」をクリック。
f:id:hmmr:20200310214639j:plain

6.時間を設定して「次へ」をクリック。ここでは朝の5時10分とします。
f:id:hmmr:20200310214810j:plain

 ※バックアップ中に作業をしていると、高確率でバックアップが失敗します。
  自分が絶対に作業をしていない&パソコンを起動している時間を選びましょう。

7.プログラムの開始を選択して「次へ」をクリック。
f:id:hmmr:20200310214905j:plain

8.「参照」から、作っておいた「BackUp.bat」を選択して「次へ」をクリック。
f:id:hmmr:20200310214949j:plain
f:id:hmmr:20200310215239j:plain

9.「完了」をクリック。
f:id:hmmr:20200310215028j:plain

※ここまででよいのですが、私の場合は直前に再起動タスクを入れているのでログオフした状態でバックアップタスクの時間を迎えてしまいます。このままではログオフ時にバックアップタスクが実行されないので、ログオフしていてもタスクが実行されるように変更する必要があります。

10.「日次バックアップ」のタスクをダブルクリックします。
f:id:hmmr:20200312011325j:plain

11.「ユーザーがログオンしているかどうかにかかわらず実行する」にチェックをいれて「OK」をクリックします。
※これを選ぶと、ログオンしているかどうかにかかわらず、パソコンの電源がついていればバックグラウンドで実行してくれます。
f:id:hmmr:20200312011605j:plain

以上で終了です。

追記(2020/03/24)

このようになります。
f:id:hmmr:20200324192020p:plain

暇あればバッチの改良するかも?

バッチとタスクスケジューラでなるべく簡単にフルバックアップを取得する(前編)

この記事は、Windows標準装備のバッチ処理とタスクスケジューラを用いて、簡易的だけど本格的(?)にバックアップを取得する手順を書いています。導入は以下の記事になりますので、軽くのぞいてみてください。


hmmr.hateblo.jp


ここから、具体的な手順を記載していきます。

1.バッチの作成

1.メモ帳を開きます。
f:id:hmmr:20200310211702j:plain

2.前の記事のテキストをすべて貼り付けます。
f:id:hmmr:20200310211841j:plain

3.ファイル→名前をつけて保存
f:id:hmmr:20200310211955j:plain

4.次のようにして保存をクリック。
・保存先→任意の場所
 ※ここではデスクトップ
・ファイル名→「BackUp.bat」
・ファイルの種類→「すべてのファイル(*.*)」
文字コード→「ANSI
f:id:hmmr:20200310212137j:plain

5.できた「Backupo.bat」を右クリック→編集をクリック。
f:id:hmmr:20200310212316j:plain

6.設定領域を好きなように変更します。

例えば
・バックアップしたいフォルダ→C:\work
・バックアップ先のHDD→Eドライブ
・保持するバックアップデータの世代数→7

の時は、

set BACKUP_FOLDER=C:\work

set DRIVE_NAME=E

set DATA_ERA=7

と書きます。

存在しないドライブを指定してはいけません

7.変更したら上書き保存します。

8.バッチファイルを適当な場所に保存します。
 ※ここでは例として、「C:\bat」フォルダに入れます。

f:id:hmmr:20200310212851j:plain

9.試しに、作成した「Backup.bat」をダブルクリックで実行してみます。
 バッチ処理が始まって、正しく保存されていればOKです。
f:id:hmmr:20200310213155j:plain

私の環境では、約1.6GBが36秒で終了しました。

ここまででバッチ作成編は終わりです。お疲れさまでした。

後編に続きます。

hmmr.hateblo.jp

バッチでなるべく簡単にフルバックアップを取得する(導入)

ツイッターで、

「PC壊れた!」
「バックアップ?そんなの(知ら)ないよ!」

みたいなツイートをみたので、あまりパソコンに明るくない人でも調べたらなんとかできそうな感じで考えてみた。

フルバックアップとは
・バックアップ対象のデータを丸ごと保存する方法です。
・例えば毎日バックアップをとって、最新の7日分だけ残すようにする方法がそこそこ一般的かも?
 ※このような「〇日分が残っている」ようにする事を「バックアップの世代管理」とか言ったり言わなかったり。

・メリットとして...思い付かなかったのでググって下さい。個人的にはこれが一番好きな方法。
・デメリットとして、容量が多いほどバックアップに時間がかかるし、必要なHDDの容量も変わってくる。


ググったらもっと金かけた凄そうなのとか出るけど、基本原理は一緒だからそんな気にする必要はない。

というか、わざわざ御大層なアプリをインストールしてパソコンのリソース食わせたり、タスクスケジューラよりも面倒な設定したくない。

必要なもの

・新しいパソコン
・新品の1TB~のHDD
 ※バックアップ用なので、SSDである必要はないです。というかバックアップ用にSSDは勿体ない
 ※HDDの容量は、バックアップするフォルダの容量から計算しましょう。
 ※HDDの中のバックアップ以外のデータは消えるので、バックアップ専用のHDDにしましょう。
・データを失った悔しさ
ドデカミン

手順概要

・バックアップ用のハードディスクを繋げる
・バックアップ処理するバッチを作成する
・バッチをタスクスケジューラに登録する

注意

 バックアップ処理はパソコンを使っていない時間帯に設定しましょう。
 バックアップ中に作業を行っていると、バックアップが失敗する事が結構あります。

と、ここまで書いて時間がなったので、詳細な手順は欲しい人がいたらコメントお願いします。気づき次第のせます。
一応、パソコンにあまり明るくない人でもがんばってググればなんとかなる要素は書きました。


バックアップバッチは下記をコピペして下さい。
[backup.bat]

@echo off
title 定時バックアップ処理

echo ###################################
echo.
echo 定時バックアップ処理
echo.
echo ###################################

rem ####################################
rem 設定領域
rem 
rem ★バックアップするフォルダ
set BACKUP_FOLDER=C:\wo
rem ★バックアップ先のドライブ名
set DRIVE_NAME=D
rem ★残す世代数
set DATA_ERA=7
rem ####################################

%DRIVE_NAME%:

rem ファイル作成
set FNAME=%date:~0,4%%date:~5,2%%date:~8,2%
mkdir %FNAME%

rem バックアップ処理
robocopy %BACKUP_FOLDER% %FNAME% /s /e

rem 古い世代を削除
for /f "skip=%DATA_ERA% delims=" %%A in ('dir %DRIVE_NAME%:\ /B /O-D') do rd /s /q %%A
echo ------------------------------------------------------------------------------
echo 日次バックアップ処理が終わりました!


※Windows10 1903で作りました。多分Windows10ならどのバージョンでも行けるんじゃないかな。

【VBA】すべてのシートを印刷するマクロ

毎日毎日ある一定タイミングで台帳印刷を行う必要があったので作った。

タスクスケジューラに登録して使う。

今まで5~10分位かかってたけど、導入してからは10秒位で終わるようになった。

このまま全部コピペして、workbook_Openイベントに書けば動く。

Option Explicit
'**************************************************************************************************************************
'★タイトル:「全てのシートを印刷するマクロ」
' 作成者:hamada
Private Sub Workbook_Open()
'0.定義&初期化
    Dim a As String
    Dim b As String
    Dim c As Integer
    Dim msg As Long
    Dim msg1 As Long
    Dim shName() As String
    Dim shName1 As String
    
    b = ThisWorkbook.Name
    c = Worksheets.Count
    shName1 = ""
    ReDim shName(c) As String
    
    For c = 1 To c
        shName(c) = Worksheets(c).Name
        shName1 = shName1 & "「" & shName(c) & "」"
    Next
'1.ダイアログを出して印刷させる処理
    msg = MsgBox("ファイル名:" & b & vbCrLf & "シート:" & shName1 & vbCrLf & vbCrLf & "を印刷します。よろしいですか?", vbYesNo + vbDefaultButton2 + vbQuestion)

    If msg = vbYes Then
        Worksheets.Select
        Application.Dialogs(xlDialogPrint).Show
        msg1 = MsgBox("印刷が終了しました。このまま保存せずに閉じますか?", vbYesNo + vbDefaultButton2 + vbQuestion)
        If msg1 = vbYes Then
            If Workbooks.Count = 1 Then
                Application.Quit
                ThisWorkbook.Close savechanges:=False
            Else
                Application.DisplayAlerts = False
                ThisWorkbook.Close
                Application.DisplayAlerts = True
            End If
            
        Else
            Worksheets(1).Select
        End If
    Else
    End If
    
End Sub