なでしこを明後日の方向に

日本語プログラム言語なでしこを応援しています

なでしこで1ボタンにコピーと貼り付けを「両方」割り当てる

まずは1ボタンにコピー、1ボタンに貼り付け

「ホットキー登録」命令を使えばキーボードの特殊キーにコピーボタンを割り当てることができます。

名前 ホットキー登録 ( ほっときーとうろく )
引数 KEYにEVENTを|KEYでEVENTを
説明 ホットキーを登録する。実行したい関数名やプログラムを文字列EVENTを指定する。

以下は影の薄い「CAPS LOCK」ボタンと「TAB」ボタンに、コピー(Ctrl+C)・貼り付け(Ctrl+V)を割り当てるプログラムです。

//かんたんな例
「CAPS LOCK」「ホットキーコピー」ホットキー登録
「TAB」「ホットキー貼付」ホットキー登録
●ホットキーコピー
 『^c』キー送信
●ホットキー貼付
 『^v』キー送信

割り当てられるほうのボタン(「CAPS LOCK」など)はホットキー登録のヘルプを、
割り当てるほうのボタン(『^c』など)はキー送信のヘルプを参照してください。

ホットキー登録は母艦がアクティブじゃなくても動作します。 また、母艦が起動している間だけ有効になります。

ボタンを一つにまとめる

コピーと貼り付けのボタンを一つにまとめてみます。

ボタンを押すたびに「コピー」「貼り付け」が入れ替わるボタン

変数を使えば実現可能です。

//CAPS LOCKでコピペ
「CAPS LOCK」「ホットキーコピペ」ホットキー登録
フラグ0

●ホットキーコピペ
 もしフラグ0ならば
   『^c』キー送信 //コピー
   フラグ1
 違えば
   
『^v』キー送信 //貼り付け
   フラグ0

今どっちのモードかわかるように工夫するとより使いやすくなると思います。

ウィンドウタイトルを見て「コピー」「貼り付け」が入れ替わるボタン

ボタンを押したとき窓アクティブタイトル取得をして条件分岐で。

以下の例は「メール」のウィンドウでは「コピー」を、他のアプリでは「貼り付け」をしたい場合。

//CAPS LOCKでコピペ
「CAPS LOCK」「ホットキーコピペ」ホットキー登録

●ホットキーコピペ
 窓アクティブタイトル取得
 もしそれ「*メール*」一致するならば
   『^c』キー送信 //コピー
 違えば
   
『^v』キー送信 //貼り付け

雑感

フリーソフトでも同じことはできるのですが、文法はなでしこのほうがとっつきやすいと思います!

なでしこで別ウィンドウのサイズを変更する

ソシャゲのウィンドウがでかすぎる! しかも枠をドラッグでサイズ変更できない!

君、画面がでかすぎるって言われない?

こんな時はなでしこ(v1)でサイズ変更をしてみましょう
※ 外部ツール使用にあたるため動作対象外だったりBAN対象だったりの可能性はあります

「窓ハンドルサイズ設定」を使う

なでしこv1で指定したウィンドウのサイズを変更する方法を書いてみます。
使う命令はこれ。窓ハンドルサイズ設定

名前 窓ハンドルサイズ設定 ( まどはんどるさいずせってい )
引数 {=?}HANDLEにSIZEを
説明 HANDLEのウィンドウにSIZE「X1,Y1,X2,Y2」を設定する

引数のHANDLEは窓ハンドル検索などで取得します。

名前 窓ハンドル検索 ( まどはんどるけんさく )
引数 {=?}Aを|Aの
説明 タイトルAを持つウィンドウのハンドルを調べる。(ワイルドカードで指定可能)

窓ハンドルサイズ設定のかんたんなサンプル

//ごくごく簡単なサンプル
HANDLE=「*なでしこエディタ」窓ハンドル検索
HANDLE「100,0,900,300」窓ハンドルサイズ設定

ウィンドウタイトル「なでしこエディタ」を持つウィンドウのハンドルを取得します。(*はワイルドカード)
窓ハンドルサイズ設定でサイズを指定して出来上がり。
成功すればなでしこエディタのサイズが変わるはずです。

HANDLEについて

引数のHANDLEは変数です。 数値が入っています。
今回のHANDLEは1902140でした。

この数値はwindows(OS)がその部品(ウィンドウなど)を作る時に割り当てた番号で、一般的に「ウィンドウハンドル」と呼ばれています。
窓ハンドルサイズ設定は、OSに対して「この番号(HANDLE)のウィンドウのサイズを変更してください」と頼む命令となります。

HANDLEを使ってできること

HANDLEを引数にした命令は以下のものがあります(他にもあります)

・窓ハンドルテキスト取得 - テキスト(ウィンドウの場合はタイトル)を取得する
・窓ハンドル位置移動 - ウィンドウの位置を移動する
・窓ハンドルキー送信 - キーボードのキーを押したことにする
・窓ハンドルキャプチャ - ウィンドウを画像としてイメージ部品に描画する

・窓ハンドルサイズ設定 - ウィンドウのサイズ「X1,Y1,X2,Y2」を設定する
・窓ハンドルサイズ取得 - ウィンドウのサイズ「X1,Y1,X2,Y2」を得る
・窓ハンドル内サイズ取得 - ウィンドウのクライアントサイズ「X1,Y1,X2,Y2」を得る

ハンドルの取得方法いろいろ

ウィンドウタイトルがわかっている場合は「窓ハンドル検索」、 ウィンドウタイトルがわからない場合は「窓ハンドル座標検索」や「窓アクティブハンドル取得」でハンドルを取得します。

名前 窓ハンドル座標検索 (まどはんどるざひょうけんさく)
引数 {=?}X,Yの
説明 X,Yのウィンドウを得る

ヘルプにウィンドウを得るって書いてあるけどハンドルが返るはず

名前 窓アクティブハンドル取得 ( まどあくてぃぶはんどるしゅとく )
引数
説明 現在アクティブなウィンドウのハンドルを取得して返す。

「窓ハンドル検索」の例

//ウィンドウタイトルからHANDLEを取得する例
HANDLE=「*なでしこエディタ」窓ハンドル検索
もしHANDLE0ならば
  「見つからなかった」表示
違えば
  
HANDLE窓ハンドルテキスト取得
  それ表示

ハンドルが0だった場合、「見つからなかった」ということですので、エラー処理を入れておきます。 同じタイトルを持つウィンドウが複数あると誤爆する可能性があります。
タイトルだけでウィンドウを特定できるならこれで十分でしょう。

「窓ハンドル座標検索」の例

窓ハンドル座標検索」ではマウスカーソルの座標にあるウィンドウのハンドルを取得するのに便利です。 「母艦のキー押した時」や「ホットキー登録」のイベントに組み込むとよさそう。

母艦キー押した時~イベント

●イベント
 x=机上マウスX
 y=机上マウスY
 HANDLE=x,y窓ハンドル座標検索
 HANDLE窓ハンドルテキスト取得
 それ表示

窓ハンドルサイズ設定の注意点

ハンドルが取れたらサイズを指定するだけです。
ただし「窓ハンドルサイズ設定」命令の引数SIZEは「X1,Y1,X2,Y2」です。 X,Y,W,Hではないことに注意します。

割合のサイズにする

「ゲームのウィンドウでかいなー80%くらいにならないかなー」という時はまず元のサイズを取得するわけですが・・・

この時、「窓ハンドルサイズ取得」で得たサイズに0.8を掛けると縦横比が歪みます
この場合「窓ハンドル内サイズ取得」で得たサイズを使いましょう。

差はタイトルバーや左右と下のふちの部分です。

//CAPS LOCKを押すとアクティブな窓のサイズが80%になるプログラム
「CAPS LOCK」「変更適用」ホットキー登録

●変更適用
 HANDLE=窓アクティブハンドル取得
 HANDLE窓ハンドル内サイズ取得 //「0,0,640,400」などが返る
 それ「,」区切る
 それ「,,内W,内H」変数分配 //x,yは要らない
 
 HANDLE窓ハンドルサイズ取得 //外枠を含むサイズ
 元SIZEそれ
 それ「,」区切る
 それ「外X1,外Y1,外X2,外Y2」変数分配
 
 //クライアント部分を0.8倍にする
 新内W = 整数部分(内W * 0.8)
 新内H = 整数部分(内H * 0.8)
 新外X2 = 外X2 -内W +新内W
 新外Y2 = 外Y2 -内H +新内H
 新SIZE=「{外X1},{外Y1},{新外X2},{新外Y2}」
 HANDLE新SIZE窓ハンドルサイズ設定

実行結果

なでしこ3の「もし」構文で「もし」の省略ができるようになった

公式の例文を確認

v3.4.26(2024/1/1) 「もし」構文で「もし」の省略について *
「もし…ならば」構文の「もし」を省略できる場合があります。それは『等しい』や『一致』命令を使って条件式を記述する場合です。以下のように記述できます。

A=30
A30等しいならば
  「等しい」表示
違えば
  
「等しくない」表示
ここまで

もしを省略したもし構文・・・いわばifを省略したif文。

さっそく実験してみましょう。 2024/1/17時点のなでしこv3.4.26を使用しています。

・OKなパターン  命令
・ムリなパターン1 変数
・ムリなパターン2 比較演算子
・なぞなパターン でなければ
・アリなパターン 

に分けて紹介します。

OKなパターン 命令

(命令用いた文)ならばと書くパターンでは「もし」を省略できます。

A=30
A30等しいならば1表示 //OK
A30以上ならば1表示 //OK
A50未満ならば1表示 //OK
A偶数ならば1表示  //OK
A10から50範囲内ならば1表示 //OK

「等しい」「以上」「未満」「偶数」「範囲内」は引数を取る命令です。 「もし」がなくても自然に見えますね。

key存在するならば //ローカルストレージ OK
AB辞書キー存在するならば //OK

「存在する」形も見た目よしですね。

A=30
AND (A,2)ならば1表示 //ビット演算 OK
A「3」何文字目ならば1表示 //文字列処理 OK
A「3」出現回数ならば1表示 //文字列処理 OK
A数列判定ならば1表示 //文字種類 OK

関数ならば文法的にはOKとされているので、上記は実行できます。
見た目が美しくないので工夫したいところです。 送り仮名でごまかせるかもしれません。

A「3」何文字目かならば // OK
A数列判定されたならば // OK

ムリなパターン1 変数

(変数)ならばと書くパターンはエラーとなります。(v3.4.26時点)

//例
フラグ
フラグならば1表示 //エラー
それならば1表示  //エラー
そうならば1表示  //エラー

惜しいですね。

ムリなパターン2 比較演算子

比較演算子の式はダメです。(v3.4.26時点) 比較演算子は<、>、=、なんかを使うやつです。

//ダメ
A=30
(A<>10)ならば //エラー
(A==30)ならば //エラー
A30ならば  //エラー

文法エラーとなります(3.4.26時点)
AがBならばの形もエラーとなります。 命令でやりましょう。

余談:なでしこ1では?

なでしこ1では比較演算子でもしを省略するとエラーにならず変な挙動をします。

A30
(A==30)ならば1表示
A表示 //→30

は正常に動作しますが

A30
A==30ならば1表示
A表示 //→なにも表示されない

カッコをはずすとAの中身がnilになります。 こわい!
なでしこ1でもしの省略は使わないほうがいいと思います。

なぞなパターン でなければ

「ならば」の否定形「でなければ」はどうなのかと言うと、

A30
A偶数ならば1表示 //→表示される
A偶数でなければ1表示 //→表示される

「偶数ならば」「偶数でなければ」で両方1が表示されてしまいました。
エラーにならず、結果がおかしいので使わないようにしましょう。(3.4.26時点)

アリなパターン 

関数「ある」「ない」を定義してみます。
※ なでしこv1には「ある」「ない」が命令として登録されているので混同に注意

●(xで|xが|xに)ある。!!(x)を戻す。。。
●(xで|xが|xに)ない。!(x)を戻す。。。
A=30
A「3」何文字目かあるならば1表示
A「3」出現回数あるならば1表示
A要素数あるならば1表示

ある程度は読みやすくなった気がします。

その他

条件式に「配列検索」を使う場合についてはうまい書き方が思いつきませんでした。

●あるを定義した場合でも
そうであるならば1表示はエラーとなりました。残念。

なでしこ1で画像をエクセル形式にする

「Image to Excel」というWebアプリが窓の杜で紹介されていました

 ときどき画像ファイルを「Microsoft Excel」ファイルに変換したいなぁって思うことはありませんか? ありますよね!? そんな人に朗報です!

forest.watch.impress.co.jp

作者曰く、

画像をExcelファイル(.xlsx)に変換するクソアプリ「Image to Excel」を公開しました。 セル1つ1つの背景色を変えることで画像を表現しています。

これをなでしこ1で作ってみたいと思います!

要件

画像を受け取り、リサイズする。画素を1つ1つ読み取って、エクセルのセルに着色していく。

これをプログラムでやるのが簡単か否か?

…簡単です! 日本語プログラム言語「なでしこ」なら! 外部ライブラリを取り込まずに20行程度で! 実現できるんです!

完成品

以下はなでしこ1のプログラムです。

cw=100
ch=100
作業とはイメージ
可視オフ
「母艦に画像ファイルをドロップしてね」表示

母艦ファイルドロップ許可オン
母艦ファイルドロップした時
 作業画像母艦ドロップファイル
 作業cw,ch画像比率変えずリサイズ
 
 エクセル起動
 エクセル新規ブック
 エクセル全選択
 3エクセル選択行高さ設定
 0.3エクセル選択列幅設定
 
 x1から作業まで繰り返す
   y1から作業高さまで繰り返す
     y,xエクセルセル名取得してそれエクセル選択
     作業x-1,y-1から画像色取得してそれエクセル着色

実行結果

実行すると「母艦に画像ファイルをドロップしてね」と書かれたウィンドウが現れます。
画像をドロップするとエクセルが起動してセルに色を塗ります。
以下はマリオRPGのサイトからとってきた画像を使用した例

実行結果

できました☆

解説

画像のロード準備

以下の部分は画像を受け取る準備です。

作業とはイメージはイメージ部品の作成です。 画像を設定すると自動でロードしてくれます。

母艦と言うのはメインウィンドウのこと。 今回はドロップした画像ファイルをエクセルに転記していく方針です。

画像比率変えずリサイズはなでしこの標準命令です。 ここではcw=100,ch=100におさまるようにリサイズしています。

cw=100
ch=100
作業とはイメージ
可視オフ
「母艦に画像ファイルをドロップしてね」表示

母艦ファイルドロップ許可オン
母艦ファイルドロップした時
 作業画像母艦ドロップファイル
 作業cw,ch画像比率変えずリサイズ

エクセル方眼紙の作成

続く処理はエクセル方眼紙の作成です。

書いてあることは謎の手順書…ではなく、エクセルを操作する命令です。 いずれもなでしこの標準命令です。

 エクセル起動
 エクセル新規ブック
 エクセル全選択
 3エクセル選択行高さ設定
 0.3エクセル選択列幅設定

色の転記

続く以下の処理は色の転記です。多少プログラムらしい姿ですね。

行,列を数値で指定して"A1"形式の座標に変換する命令エクセルセル名取得を使ってセルを選択します。 行,列の順に引数を取るのでx,yを逆にして座標を指定します。

画像から色を取得して、選択したセルを着色します。 画像は座標が0,0から始まるのに対し、エクセルは1,1から始まるのでズラしています。

 x1から作業まで繰り返す
   y1から作業高さまで繰り返す
     y,xエクセルセル名取得して、それエクセル選択
     作業x-1,y-1から画像色取得して、それエクセル着色

なでしこ1ではインデントでループのブロックをあらわします。Python風ですね。
インデントには全角スペースが推奨されています。

おわりに

なでしこ1で「Image to Excel」を再現してみました。
ただし出力速度はそうとうもっさりなので、本家のアプリを使うと良いと思います。

関係ないけど、シンタックスハイライトのカンマと読点が見にくいので直したい。

なでしこ1の「マウス移動」で座標がズレる原因

なでしこ1の「マウス移動」などで指定した位置にマウス移動しない!
または母艦の位置が思った場所に行かない!
という現象があります。

windowsのディスプレイ設定の倍率が100%でないときに発生します。
高解像度のノートPCとかだと、推奨(初期値)が200%になっている模様。

windows10の設定画面より

windows11の設定画面より

試してみた

母艦のX座標を100に指定します。
窓キャプチャで画像を撮り、画像のX=100のところに赤線を引きます。
これをディスプレイの設定100%と150%で実行結果を見比べます。

母艦位置「100,0」 //←母艦のX=100
1秒待つ
AAAとはイメージ
AAA「デスクトップ」窓キャプチャ
線色赤色線太さ2
AAA100,0から100,100 //←画像のx=100のところに赤線

実行結果(なでしこエディタを最大化して実行)

・ディスプレイ100%時

・ディスプレイ150%時

画像の右側の「なでしこ」のウィンドウが母艦です。
赤線と母艦は両方ともX=100を指定していますが、150%にするとずいぶん離れてしまいました。
画像上では母艦はX=150あたりにいます。

つまり、窓キャプチャの画像で調べた座標(X=100)を指定すると、150%ズレた位置(X=150)くらいにいくのです。
スクリーンショットツール+ペイントで調べた座標でも同様です。

このズレはマウス移動でも同様です。
X=100を指定してマウス移動すると、画像上のX=150あたりに行きます。

思った位置(=画像で調べた位置)にマウスカーソルが移動しないことになります。

画像の座標から補正する

画像で調べた位置にマウスカーソルが行くためにはどうしたらよいかと言うと、ディスプレイの設定を見て150%なら100/150(125%なら100/125)を座標に乗算します。

プログラムからディスプレイの拡大率をおしはかる方法は、よくわかりませんでした!

母艦位置「{100*100/150},0」 //←X=100に 100/150 を乗算
1秒待つ
AAAとはイメージ
AAA「デスクトップ」窓キャプチャ
線色赤色線太さ2
AAA100,0から100,100

実行結果

赤線がX=100、右のなでしこウィンドウが母艦(X=100*100/150)

座標を調べなおす場合

前述の通り、画像に撮ってから座標を調べる方法がアテにならないことがわかりました。

自動クリックするプログラムをこれから作る場合、座標は机上マウスX,机上マウスYで調べるとよいです。
これで得られる座標はそのままマウス移動に使えます。

以下のプログラムはキーを押すとマウス移動命令を生成してクリップボードにコピーするプログラムです。

母艦キー押した時
  x=机上マウスX
  y=机上マウスY
  母艦タイトル「{x},{y}」
  「{x},{y}へマウス移動」コピー //プログラム文の生成

本命のプログラムにコピーしたプログラムを貼りつけしていく感じ。

なでしこのエディタの機能について確認する

マウスの調子が悪いので画像に赤線引いたりはできなかった

マニュアル探査艦で探す

ヘルプの中にあります。使い方がわからない命令を検索するときに便利。
サンプルも充実。

単語補完(X)

ショートカットはCtrl+Space
検索メニューにあるのですが、使用頻度が高いのでショートカットを覚えておきましょう。
たとえば「配列」と打ってCtrl+Spaceを押すと左に「配列」を含む命令が表示されます

グループに対して押すとメンバが表示されます

区切り線を挿入

カーソルの位置に以下のコメントが挿入されます

#-----------------------------------------------------------------------

ショートカットはCtrl+L

インデント→とインデント←

範囲選択してから押します。
選択した範囲のインデントを増やしたり減らしたりできます。

インデント→はCtrl+Shift+I
インデント←はCtrl+Shift+U

IとUはキーボード上で並んでいるので一度押してみるといいと思います。 エディタの最終行の[EOF]に使うとエラー出るのが残念。

タブ→全角スペース(推奨)(V)

なでしこではインデントをタブ・半角スペース・全角スペースを使用できますが、全角スペースに置換してそろえることができます。

選択した範囲に実行します
機能名はタブ→全角ですが、半角スペースも全角スペースになります。

実行時にクリップボード関連のエラーが出ることがあるみたいです。

しおり>記録・ジャンプ

記録でエディタのカーソル位置を記録します。
ジャンプで記録した位置にカーソルを移動します。
5か所まで記録可能。

プログラムが縦に長くなってきたときに便利です。

とにかく全部終了

起動中のなでしこのウィンドウをとにかく全部終了します。
このエディタから実行されたものでなくても終了します。

非常時に使用すると思うのですが、ショートカットはありません。残念。

なでしこ1の動的生成した部品がエラーになってしまう件

※ 記事が書かれた時点のなでしこはv1.588です。

なでしこ1で動的生成した部品について、以前のバージョンでは起きなかったバグがあるようです。
GUI部品のイベント中に動的生成するとエラーになってしまいます。

わかりやすく言うと「クリックした時は~」などの部品イベント中に 「(部品名)として作成」の命令を使用した時、ということです。 作成した部品に「→」でアクセスするとエラーを吐きます

サンプルプログラムはこちら

作成ボタンとはボタン
そのクリックした時   //GUI部品のイベント中に
  ボタン群[0]ボタンして作成  //部品を作成すると
  ボタン群[0]X20  //エラーになる(生成に不具合)

・エラーメッセージ

[なでしこ(vnako)] ver.1.588 [作成ボタンのクリック時を実行中のエラー] [エラー] vnako.nako(98): 関数『VCL_SET』の実行中にエラーが起きました。 VCL_SETでプロパティ番号(10)の設定で、オブジェクトの値が(nil)です。オブジェクトが生成されていない可能性があります。(関数)
[エラー] vnako.nako(98): (関数定義)
[エラー] com.nadesi.exe.nakopad.temp.bak1.nako(4): (代入)

なでしこ1.588ではエラーとなりました。
なでしこ1.584では正常に動作しました。

なでしこ1.588では「自身」の更新タイミングがおかしい?

なでしこで部品を作成した時にまず呼ばれるのは・作る~のメンバです。
たぶん他言語では「コンストラクタ」と呼ばれているやつ。

コンストラクタ(constructor:構築者)とは、クラスからオブジェクトを作成した際に、自動的に実行される特殊なメソッドのこと

ボタンの・作る~はvnako.nakoに書かれています。

■ボタン +ウィンドウ部品 +ボタンイベントプロパティ +ドロッププロパティ
 ・種類{="ボタン"}
 ・作る
   オブジェクト、VCL_CREATE(自身, 名前, VCL_GUI_BUTTON)
   テキスト、名前から「ボタン」初期テキスト切り出し

・作る~の中にあるVCL_CREATEという関数が実際にボタンを作っている関数です。
1.588では、この引数「自身」「名前」が動的生成した部品(ボタン群[0])のものではなく、イベントが発生した部品(作成ボタン)のほうを指している…気がします!

以下のプログラムから確かめることができます。

■ボタンB +ボタン
 ・作る
   自身名前言う

作成ボタンとはボタン
そのクリックした時
  ボタン群[0]ボタンBして作成
  ボタン群[0]名前言う

作る~の中で自身の名前作成ボタン
ボタン群[0]→名前_AUTO1962となりました。

本来、作る~の中でも自身の名前_AUTO1962になってないといけないはずです。

バグ報告掲示板の様子

「なでしこv1」開発掲示板

↑これが該当スレと思われます。

自分はこんな複雑なグループの使い方しないしー、と思っていたのですが、 クリックした時作成できないとか身近な存在でした。

なでしこ1.588での回避法

どうやら作成の最中に呼ばれた作るのときだけ自身がおかしいので
作成が終わった後に作るの中身を呼びます。

ボタンを継承して作るの中身を空にし、作る2として元の作るのコードを配置。
作成が終わった後に作る2を呼びます。

■ボタンB +ボタン //←ボタンのグループを継承
 ・作る
 ・作る2 //ここに元の作るのコードを配置
   オブジェクト、VCL_CREATE(自身, 名前, VCL_GUI_BUTTON)
   テキスト、名前から「ボタン」初期テキスト切り出し

作成ボタンとはボタン
そのクリックした時
  ボタン群[0]ボタンBして作成 //作成が終わった後に
  ボタン群[0]作る2 //作るだったものを呼ぶ
  ボタン群[0]X20

…バグが直るまでイベント中に動的生成するのは控えた方がよいでしょうね。