112636
UWSC 仮 掲示板
投稿時に「証明書が不正です」と出る場合には、JavaScriptをオン
動作不具合での質問の場合には環境を表記(OS,バージョン等)
タイトルは内容を表し、内容はネットゲーム関係禁止
自身でコードを書く気の無いナマケモノは特に質問禁止
失敗作でもコードを投稿すること(具体性の無い質問は無視される可能性大)

UWSC掲示板 が復活することを祈り、それまでの繋ぎとして。
環境設定[s7777777]

エラー / あんき
リンクボタンを押すと以下のエラーが出るのですが、意味を辞書で引いてもわかりません、何か対処の仕方ございますでしょうか。
for-next could not convert variant of type (dispatch)into type (oleStr)
for elem in obj.document.GetElementsBY TagName("input")

No.1203 2021/02/18(Thu) 18:05:17

Re: エラー / Rayna
>>1203 あんき さん
 Dispatch型(オブジェクト)からoleStr型に型変換失敗してますね
 Dispatch型に For-In 出来るコレクションがないだけだとメンバーが見つかりませんとでるので
 obj.document.getElementsByTagName("input") に NOTHING が返ってるとかですかね

 渡そうとしてるオブジェクトをPrintするなりして内容を確認してみてください

No.1204 2021/02/18(Thu) 18:39:37

Re: エラー / stuncloud
> GetElementsBY TagName
ここの半スペのせい?かも?
(通常なら文字列にする処理が不要な気がするので)

No.1206 2021/02/18(Thu) 20:02:24
反応がない / sousou
お世話になります。
以下、簡単なものなのに、ボタンを押しても反応が遅い、反応しない場合(ダブルクリックなど)があります、多くのボタンがある場合、必ず反応しないと誤動作になります、一瞬でも押したら、必ず反応させる方法はありますでしょうか。
最低でも1つのボタンは、確実にダブルクリックでも2回表示させたいのです。

obj = CREATEFORM("about:blank", "Calc", True, FOM_NOHIDE) 
obj.Document.write(計算フォーム)      
while obj.Visible              
  if GETFORMDATA("CalBtn1") then print "1" 
  if GETFORMDATA("CalBtn2") then print "2" 
wend

TextBlock 計算フォーム  
 <form method='POST'>        
<input type='submit' value=' 計算1 ' name='CalBtn1'>

<input type='submit' value=' 計算2 ' name='CalBtn2'>

 </form>
EndTextBlock

No.1199 2021/02/18(Thu) 10:48:06

Re: 反応がない / stuncloud
oleeventを使います
oleeventによりボタンがクリックされた際に任意の関数を実行できます

-------
obj = CREATEFORM("about:blank", "Calc", True, FOM_NOHIDE)
obj.Document.write(計算フォーム)

// クリック時のイベントハンドラを指定
// ここではすべてのinput要素に対して指定を行う
for elem in obj.document.GetElementsByTagName("input")
 oleevent(elem, "HTMLInputTextElementEvents2", "onclick", "onclick")
 oleevent(elem, "HTMLInputTextElementEvents2", "ondblclick", "onclick")
next

while obj.Visible
 sleep(0.1)
wend

TextBlock 計算フォーム  
 <form method='POST'>        
<input type='submit' value=' 計算1 ' name='CalBtn1'>

<input type='submit' value=' 計算2 ' name='CalBtn2'>

 </form>
EndTextBlock

// ボタンクリック時に呼び出される関数
procedure onclick()
 select EVENT_PRM[0].srcElement.name // イベント元になるエレメントのnameにより処理を分岐
  case "CalBtn1"
   print 1
  case "CalBtn2"
   print 2
 selend
fend
-------

oleeventを2回呼んでる理由は
・onclickだけだとダブルクリック時の2回目のクリックを取りこぼす
・ondblclickでダブルクリック時のイベントを拾えるので取りこぼしをカバーできる
からです

No.1200 2021/02/18(Thu) 11:54:45

Re: 反応がない / sousou
stuncloud様ありがとうございます、oleeventの使い方研究します。
No.1202 2021/02/18(Thu) 15:18:23
オブジェクトの状態取得 / あかは
会社で使っているソフトに ファンクションバー というのがあります。
ファンクションバーの表示状態を確認したいのですが、ファンクションバーはカスタマイズ可能なので、できれば画像判定以外で確認したいと思ったのですが、行き詰まってしまいました。

とりあえず getid(get_frompoint_obj) でIDを取得して st_title と st_class を確認したところタイトルは無しで、クラスはBCGPControlBar:40000000:8:10003:10でしたので、これでIDを取得してst_visibleで確認しようかと思いまして、

getid("","BCGPControlBar:40000000:8:10003:10")を試しましたが-1が返ってくるので見つからないのだと思います。
(まあ本来ウィンドウのIDを返す関数らしいので、当然なのでしょうが)

なにか良い手段がありましたらご教授お願いします。

No.1195 2021/02/17(Wed) 14:03:57

Re: オブジェクトの状態取得 / stuncloud
そのファンクションバーのあるウィンドウのIDをgetidで取得し

bFunctionBar = false
for cid in getallwin(id)
 if pos("BCGPControlBar", status(cid, ST_CLASS)) > 1 and status(cid, ST_TITLE) = "" then
  bbFunctionBar = true
  break
 endif
fend

if bFunctionBar then
 msgbox("ファンクションバーがありました")
else
 msgbox("ファンクションバーはありませんでした")
endif

みたいなことができるかもしれません
これは BCGPControlBar から始まるクラス名を持つ子ウィンドウが他にない場合に有効です
なんなら BCGPControlBar:40000000:8:10003:10 をposに渡してもいいかもしれませんが
後ろの数値のあたりが一意かどうかあやしい (起動する度に変化するということもあるかも?) ので
このような書き方にしてみました
> getid("","BCGPControlBar:40000000:8:10003:10")
が-1だったということもありますし

あとそもそもの話で getid(get_frompoint_obj) したものが本当にファンクションバーかも疑わねばなりません
(実は見えてるもののIDじゃなかったということがよくあるので…)
なので getallwin(id) で子ウィンドウ一覧が取れるようであれば、ファンクションバーの有無でその状態を確認する
という作業が必要になるかもしれません

for cid in getallwin(id)
 print status(cid, ST_CLASS) // クラス名調査用
 print status(cid, ST_VISIBLE) // 可視かどうか (ファンクションバーがなくても子ウィンドウとしては存在してて見えてないだけ、かどうかの確認)
 print status(cid, ST_CLX) // クライアント座標を確認することでおおよそどのへんにあるかわかる
 print status(cid, ST_CLY) // 同上
fend

など必要に応じてstatus()していく

No.1196 2021/02/17(Wed) 15:52:25

Re: オブジェクトの状態取得 / Rayna
>>1195 あかは さん
 子ウインドウを獲得する場合は
 GetCtlHnd か GetAllWinの子ウインドウ列挙 を使います
 親ウインドウIDが取れてれば獲得できるはず...

 うまく行かない場合は GET_FROMPOINT_OBJ で得たIDの ST_PARENT を
 辿っていくとどれが親かわかりやすいです


//| 追記(2021/02/18) |//////////
// 上げるほどのことでもないので追記
// GetCtlHnd の戻値ですが割と組込関数でなんとかなっちゃいます

 Dim idWnd = GetId(GET_ACTIVE_WIN) // = GetId([Window Title], [Window Class])
 While idWnd=GetId(GET_ACTIVE_WIN)
  Sleep(0.1)
 WEnd
 idWnd = GetId(GET_ACTIVE_WIN)
 Dim idWndCtl = HndToId(GetCtlHnd(idWnd, "BCGPControlBar:40000000:8:10003:10"))
 IfB GetId(GET_ACTIVE_WIN)=idWnd Then
  IfB Status(idWndCtl, ST_VISIBLE)=TRUE Then
   Print GetWinNameStrs(idWndCtl)+" は表示状態"
  ElseIf Status(idWnd, ST_ISID)=FALSE Then
   Print "親が獲得できてないか閉じられている"
  ElseIf Status(idWndCtl, ST_ISID)=FALSE Then
   Print "子が獲得できてないか閉じられている"
  Else
   Print GetWinNameStrs(idWndCtl)+" は非表示状態"
  EndIf
 EndIf
 Print

 PutChildWindowTree(idWnd) // ウインドウ親子関係一覧出力
 While Status(GetId(GET_LOGPRINT_WIN),ST_VISIBLE);Sleep(0.7);WEnd
 Procedure PutChildWindowTree(idWnd, nIndent=0)
  Dim idWndCtl, sIndent=Format(" ", (nIndent+1)*2)
  If nIndent=0 Then Print GetWinNameStrs(idWnd)+" の子ウインドウ一覧"
  For idWndCtl In GetAllWin(idWnd)
   If Status(idWndCtl, ST_PARENT)<>idWnd Then Continue
   Print sIndent+GetWinNameStrs(idWndCtl)
   PutChildWindowTree(idWndCtl, nIndent+1)
  Next
 FEnd
 Function GetWinNameStrs(idWnd)
  RESULT = "[<#DBL>"+Status(idWnd,ST_TITLE)+"<#DBL>, <#DBL>"+Status(idWnd,ST_CLASS)+"<#DBL>]"
  RESULT = Replace(RESULT, "<#CR>", "<CR>") // Editコントロールとかでテキストが ST_TITLE になってるの対策
 FEnd

No.1197 2021/02/17(Wed) 16:01:07

Re: オブジェクトの状態取得 / しろまさ
// GetCtlHnd例(VncViewer例 要変更)

//ウィンドウIDの取得
  id_W = GetID("New TightVNC Connection", "#32770", 0.2)
  hndW = GetCtlHND(id_W, "Button", 2)
// hndW = GetCtlHND(id_W, "BCGPControlBar:40000000:8:10003:10", 1)

//objClass[ Button ]の取得と設定
  o_Text = objText(hndW)  // 取得 o_Text= "&Connect"
  MsgBox(o_Text)
  objText(hndW, "asd")  // 設定
// objText(hndW, "asd", TRUE)  // 設定(入力確認付)

Function  objText(hndW, a_SetText = NULL, a_ChkText = FALSE)
  Result  = ""
  Dim Buff  = Format(ChrB(0), $FF), tBuff
  Ifb  a_SetText <> NULL
    SendMessageA(hndW, WM_SETTEXT, 0, a_SetText)
    Ifb a_ChkText
      Repeat
        tBuff  = Buff
        SendMessageA(hndW, WM_GETTEXT, $FF, tBuff)
      Until  Trim(tBuff) = a_SetText
    EndIf
  Else
    If  SendMessageA(hndW, WM_GETTEXT, $FF, Buff) > 0  Then Result  = Trim(Buff)
  EndIf
FEnd
DEF_DLL  SendMessageA(HWND, UINT, LONG, var PCHAR) :LONG :user32.DLL
  Const  WM_SETTEXT  = $000C
  Const  WM_GETTEXT  = $000D

No.1198 2021/02/17(Wed) 16:57:14

Re: オブジェクトの状態取得 / あかは
みなさんありがとうございます。

ウィンドウにくっついているオブジェクトも、ウィンドウという扱いで良いのですね。
とりあえず getallwin()で子ウィンドウを数えたところ、60もあるので
>>1196
を参考に

wID = getid(,"Afx")
for cID in getallwin(wID)
if pos("BCGPControlBar",status(cID, st_class)) then print "★★★★"
print "cID("+ cID + ") = " + status(cID, st_class)
print status(cID, st_visible)
print "X= " + status(cID, st_clx) + ", Y= " + status(cID, ST_CLY)
print "W= " + status(cID, st_clwidth) + ", H= " + status(cID, st_clheight) + "<#CR>"
next

とスクリプトを書いて実行したところ、表示状態の違いで

★★★★
cID(37)= BCGPControlBar:40000000:8:10003:10
True
X= 0, Y= 1033
W= 1920, H= 22

★★★★
cID(19)= BCGPControlBar:40000000:8:10003:10
False
X= 0, Y= 24
W= 318, H= 223

とそれぞれ確認できました。

親ウィンドウの st_title は 業務毎に異なり、st_class は Afx〇〇(〇〇は変動する)でかつ、別の作業で立ち上げているウインドウもクラスが Afx〇〇(しかもそれぞれのウィンドウにファンクションバーがあり、表示状態が異なる)
なので、一意の値での特定が困難なのですが、アクティブウィンドウを対象にする事でなんとかできそうです。(お茶を濁すとも言う)

No.1201 2021/02/18(Thu) 11:59:48
このエラーはなんでしょうか? / 太郎
おせわになります。
毎朝モニターを入れるだけの簡単なプログラムなのですが
今朝下記のようなエラーのポップアップがでておりました。
このエラーは一体何なのでしょうか?
external exception c0000006

No.1193 2021/02/17(Wed) 09:31:43

Re: このエラーはなんでしょうか? / stuncloud
このへんですかねぇ
https://stackoverflow.com/questions/1317886/external-exception-c0000006
これはアプリケーション自身が取り外し可能なディスクに置いてあり、自身を実行中にそのディスクを取り外すとこのエラーが発生するという話、ですかね
プログラム全部をメモリにロードするようにして回避しなされ、ということみたいですね

ほかにも検索するといろいろ出てくるんですが、以下であれば
https://wiki.agencysystems.com/wiki/Error:_External_Exception_C0000006
アプリケーションが共有フォルダに置かれていて途中でそこへのアクセスが失われるとこのエラーが出るという話っぽいです

要するに途中でUWSC.EXEかあるいは必要なDLLだとかにアクセスできなくなってる?ということでしょうかね?

なので

UWSC自身、スクリプト、またはその両方が共有フォルダに置いてあるのであればローカルに置いてみる
いずれもローカルにあるのにこの現象が発生するならファイルIOがおかしくなってるかもしれないのでCHKDSKなどによる診断や修復を試みる
それでもどうにもならないならストレージを交換する

といった対処法がもしかしたら有効かもしれません
エラーが頻発するようでしたらお試しください

No.1194 2021/02/17(Wed) 11:07:17
GETKEYSTATEについて / あかは
手元に getkeystate(3) で [Ctrl] + [Pause/Break] を検出するスクリプトがあるのですが、この3が何処から出てきたのか、どういった数字なのか、ネットを検索してもさっぱり分かりません。
何方か御存知ないでしょうか。

No.1190 2021/02/15(Mon) 14:42:48

Re: GETKEYSTATEについて / Rayna
>>1190 あかは さん
 ヘルプに書かれていないキーコードは以下が参考になると思います
 ttps://docs.microsoft.com/ja-jp/windows/win32/inputdev/virtual-key-codes
 ttp://kts.sakaiweb.com/virtualkeycodes.html


//| 追記(2021/02/15) |//////////
>>1192
 UWSCの内部で扱われているAPIの定数ですね
 そのうちのよく使う定数だけをピックアップして
 わかりやすく(例えば VK_LWIN -> VK_WIN みたいな)再定義したものが
 UWSCのヘルプに書かれている VK_* の定数です

No.1191 2021/02/15(Mon) 15:30:17

Re: GETKEYSTATEについて / あかは
仮想キーコード一覧が大変参考になりました、ありがとうございました。
プログラムはさっぱりなのですが、これは、UWSCが規定している数値?ではないんですね、探しても解らなかった訳です。

No.1192 2021/02/15(Mon) 15:48:30
数値の桁数をそろえたい / かーくん
1〜9は0001〜0009の文字列
10〜99は0010〜0099
100〜999は0100〜0999
1000〜9999はそのまま
を一行でする方法はありますか?

桁数を調べてif文を使うと何行にもなってしまうし
format関数でやろうとしましたが、上手く行きませんでした。
format("000" + x ,3)

No.1182 2021/02/14(Sun) 03:28:36

Re: 数値の桁数をそろえたい / satocha
確かにformat関数の動きがおかしいですね。
仕方ないので
replace(format(x,4)," ","0")
でどうでしょうか。

No.1183 2021/02/14(Sun) 04:10:31

Re: 数値の桁数をそろえたい / かーくん
satocha さん、有難うございます。
Formatで左にできたスペースを「0」に変える方法、思いつきませんでした。
これだと他の事にも応用できそうです。
 

No.1184 2021/02/14(Sun) 04:53:32

Re: 数値の桁数をそろえたい / Rayna
>>1182 かーくん さん

Dim i, x
// "000"+x で文字列型になるので
// 文字列型の前方繰り返し処理になってますね
For x In Split("1 11 111 1111", " ", FALSE, TRUE)
 Print VarType(x)=VAR_DOUBLE // True // この時点では数値型(Double型)
 Print VarType("000"+x)=VAR_USTR // True // この時点で文字列型(UStr型)にキャストされる
 Print Format("000"+x, 3)
Next

// つまり以下と同じ動作です
For i = 0 To 9
 Print "i="+i+":"+Format("string", i)
Next

// 正しくは以下の2パターン、場合によって使い分けると便利です
For x In Split("1 11 111 1111", " ", FALSE, TRUE)
 // 数値型として半角スペースで埋めて置き換え // >>1183 satocha さんの方法
 Print Replace(Format(x, 4), " ", "0")
 // 必要文字数からx文字数を引いて文字列"0"を繰り返し + x
 Print Format("0", 4-Length(x)) + x
Next

// 前者は16進数で処理するときにも対応 // デメリット:数値以外繰り返し処理, 左詰めができない
 Print Replace(Format($FF, 4, -1), " ", "0") // "00FF"
 Print Replace(Format("abc", 4, -1), " ", "0") // "abca"

// 後者は数値に限らず半角文字列に対応 // デメリット:変数を用意しないと冗長, 16進数が面倒
 x = $FF // 255
 Print Format("0", 4-Length(x)) + x // "0255"
 x = Format($FF, 0, -1) // こうすれば16進数も対応
 Print Format("0", 4-Length(x)) + x // "00FF"
 x = "abc" // 文字列
 Print Format(".", 4-Length(x)) + x // ".abc"
 x = "あ" // 全角文字列が入ってる場合はLengthBを使う(埋め文字が半角の場合のみ有効)
 Print Format(".", 4-LengthB(x)) + x // "..あ" // 右詰め
 Print x + Format(".", 4-LengthB(x)) // "あ.." // 左詰め

No.1185 2021/02/14(Sun) 10:51:06

Re: 数値の桁数をそろえたい / かーくん
Raynaさん有難うございます。
加える「0」の文字列を作って、xの左に加える方法なるほどです。
また、文字列だった場合の方法も教えて頂きありがとうございました。

No.1186 2021/02/14(Sun) 13:24:07

Re: 数値の桁数をそろえたい / しろまさ
// シンプルにこんな方法もあります。
Dim n = 99
MsgBox( Copy("000"+n, Length(n)) )

No.1189 2021/02/15(Mon) 13:11:40
多次元の連想配列の値を更新したい / cho
内容がタイトルと相違してきたので、別スレッドにしました。
No.1177 2021/02/13(Sat) 16:42:51 からの続きです。

通常の多次元と同じ書き方でSyntaxErrorが出ます。
たぶん、とても簡単なことだと思うのですが・・・


DIM v[1][1]

v[0][0] = "value" // 通常の2次元はこの書き方で代入できる
PRINT v[0][0]

hashtbl h
h["hoge"] = split("foo bar baz") // splitでSafeArrayにする
print h["hoge"][0] // foo

h["hoge"][0] = "f002" // 同じ書き方でもSyntaxErrorがでる
print h["hoge"][0]

// やってみた書き方(他言語の書き方も参考してみましたが全滅でした)
 // h["hoge"] = 0."f002"
 // h["hoge",0] = "f002"
 // h = ["hoge",[0] = "f002"]
 // h = ["hoge","f002"]
 // h = ["hoge"]["f002"]
 // h["hoge"] = 0."f002"
 // h["hoge"] = 0:"f002"
 // h["hoge"] = [0]:"f002"
 // $h["hoge"][0] = "f002"
 // h["hoge"]["0"] = "f002"
 // h["hoge"][0] = $"f002"
 // h["hoge"] = [0,"f002"]
 // h["hoge"] = [0]"f002"
 // h["hoge"[0]] = "f002"
 // h["hoge",0] = "f002"
 // h["hoge"][0] = h["hoge"]["f002"]
 // h["hoge"][0] = {"f002",,}

// あれから粘ってやってみましたが、自己解決に至りませんでした。
// 値の更新はとりあえず、置換などの後ろ向きな解決法が使えたので困ることはないと思います。
// それでも、連想の多次元を使えることを知れたのは幸運でした。ありがとうございます。
// 時間に余裕が出たら再チャレンジしてみます。

//苦肉の策。置換してSafeArrayで丸ごと更新
value = h["hoge"][0]
str = JOIN(h["hoge"])
h["hoge"] = SPLIT(REPLACE(str,value,"f003")) //値が重複する場合もあるので、カウントもする処理も追加する

print h["hoge"][0]

No.1180 2021/02/13(Sat) 19:13:41

Re: 多次元の連想配列の値を更新したい / cho
時間的にすれ違ったので、転載します。

>>  ☆ Re: EVALで値の代入したい NEW / stuncloud 引用
>> > h["hoge"][0] = "f002" // 同じ書き方でもSyntaxErrorがでる
>> うわあ、確認不足でしたごめんなさい
>> これはおそらく連想配列の要素にインデックス指定して代入、をUWSCが許容していないということだと思います
>> 値を読むだけならOKだけど代入は無理ということになりますね
>> つまりこの方法は使えない…ので忘れてください…ほんとすいません…
>> 
>> > COMオブジェを経由して使える連想配列という認識
>> そんな感じでOKです
>> 例えば連想配列を関数の戻り値にしたいけど、仕様上できないので代わりにScripting.Dictionaryを使う
>> みたいな感じで使うことがあったりなかったりします



stuncloudさんレスありがとうございます。

なるほど、仕様上できないのですね。
SyntaxError = 構文エラーなので、書き方があるのかと思いました。
わかってスッキリしました。

実は、先日の質問内容(moduleと2次元で解決できると考えた)ですが、
「適当な数字」の桁数が多かった(JANコードみたいなものです)ため、2次元配列に入れることが出来なく、解決策を考えていました。
適当な数字をなぜキーにしていたのか、うっかり忘れていました。
そこに、Scripting.Dictionaryのお話をいただけて、
もしかしたら出来るかも。という気持ちになっています。

話に出たのは偶然だったかもですが、新しいヒントをありがとうございます。
頑張ってみます。

No.1181 2021/02/13(Sat) 19:47:29

Re: 多次元の連想配列の値を更新したい / しゅん
// こんな感じ?

hashtbl h
h["hoge"] = split("foo bar baz") // splitでSafeArrayにする
print h["hoge"][0] // foo

SetHash(h, "hoge", 0, "f002")
print h["hoge"][0]


PROCEDURE SetHash(var h[], key, index, value)
  DIM sa = h[key]
  sa[index] = value
  h[key] = sa
FEND

No.1187 2021/02/15(Mon) 07:54:57

Re: 多次元の連想配列の値を更新したい / cho
しゅんさんありがとうございます。

まさしくやりたいことが実現できます。
値の重複を気にすることなく、ダイレクトに更新できる点がとてもスマートだと思いました。
その自作関数丸ごと使わせていただきます。感謝。

このスレを参考にされる方が他にもいるかもしれないので、
私が確認用に使ったコードを載せておきます。
連想配列を多次元・可変長で使う方の参考になれば幸いです。

hashtbl h
h["hoge"] = split("foo bar baz") // splitでSafeArrayにする
h["fuga"] = SPLIT("apple orange melon mango banana kiwi")
// print h["hoge"][0] // foo

SetHash(h, "hoge", 0, "f002")
// print h["hoge"][0]
SetHash(h, "fuga", 4, "GoBananas")

// 確認用
FOR i = 0 TO LENGTH(h)-1
 key = h[i,HASH_KEY]
 FOR j = 0 TO LENGTH(h[key])-1
   PRINT key+"["+j+"] = "+h[key][j]
 NEXT
NEXT

PROCEDURE SetHash(var h[], key, index, value)
  DIM sa = h[key]
  sa[index] = value
  h[key] = sa
FEND

// bananaをGoBananasに変えて洒落を利かせてみました(笑)

No.1188 2021/02/15(Mon) 11:31:07
EVALで値の代入したい / cho
お世話になります。
表題の件ですが、行き詰っているので解決できるヒントがあればお願いします。

HASHTBL Apple
HASHTBL Orange
HASHTBL Melon

TEXTBLOCK list_fruit
Apple
Orange
Melon
ENDTEXTBLOCK

DIM fruit_list[3]
Array = SPLIT(list_fruit,"<#CR>")
FOR i=0 TO LENGTH(Array)-1
  fruit_list[i] = Array[i]
  PRINT "fruit_list["+i+"] = "+fruit_list[i] // 確認用
NEXT

fruit_Number = "100" //適当な数字
Apple[fruit_Number] = "ふじ"
PRINT Apple[fruit_Number] // = ふじ と表示される
PRINT EVAL(fruit_list[0]+"[fruit_Number]") // = ふじ と表示される

// やりたいこと
  // EVAL(fruit_list[0]+"[fruit_Number]") = "紅玉" //代入して値を更新したい。ここでエラーが出る
  // PRINT EVAL(fruit_list[0]+"[fruit_Number]") // 紅玉 と表示させたい
// 試したこと(EVALは代入に:=を使うらしい)
  // ()の位置や""で囲む位置などを工夫したがエラーになる
  // EVALの重ね掛けを試してみるなど迷走中・・・
  // EVAL(EVAL(fruit_list[0]+"[fruit_Number]"):="紅玉")
  // EVAL(EVAL(fruit_list[0]+"[fruit_Number]")+":=<#DBL>紅玉<#DBL>") //エラーはでないが代入されない
// 希望の条件
  // 自作関数の引数にfruit_list[]を使ってFORで回したい
  // PUBLICは使いたくない

// よろしくお願いします。

No.1162 2021/02/11(Thu) 01:32:40

Re: EVALで値の代入したい / しゅん
// おしいですね!
EVAL(fruit_list[0]+"[fruit_Number] := <#DBL>紅玉<#DBL>") //代入して値を更新できます!
PRINT EVAL(fruit_list[0]+"[fruit_Number]") // 紅玉 と表示されます!

No.1163 2021/02/11(Thu) 09:04:21

Re: EVALで値の代入したい / Rayna
>>1162 cho さん

代入できてない場合は以下に気をつけてみてください
 代入しようとした変数が間違っている
  Eval した関数のローカル変数として作成しようとするので
  代入先ではなく新変数に入ってる可能性があります
 Evalを使用した, モジュール、関数内、関数外に同名の変数がある
  Eval は変数を外向きに探索するので 場合によっては Global. This. 等を明示しないと駄目な場合があります

これを意識しながら書くと失敗しにくいと思います
分かりづらいなら Eval しようとしてる文字列を一度 Print してみてください

以下を例にあげると
>>  // EVAL(EVAL(fruit_list[0]+"[fruit_Number]")+":=<#DBL>紅玉<#DBL>") //エラーはでないが代入されない
 Print EVAL(fruit_list[0]+"[fruit_Number]")+":=<#DBL>紅玉<#DBL>" // "ふじ:=<#DBL>紅玉<#DBL>"
 EVAL(EVAL(fruit_list[0]+"[fruit_Number]")+":=<#DBL>紅玉<#DBL>")
 Print Eval(fruit_list[0]+"[fruit_Number]") // ふじ と表示される
 Print Eval("ふじ") // 紅玉 と表示される
新規変数 ふじ に代入してますね

>>  // 自作関数の引数にfruit_list[]を使ってFORで回したい
Function f(fruit_list[])
 [] をつけると 変数, 配列, 連想配列 を引数として受けることが出来ます

No.1164 2021/02/11(Thu) 09:45:56

Re: EVALで値の代入したい / しゅん
// Raynaさん、丁寧なフォロー、ありがとうございます。
// よくよく考えると、EVAL使うのが間違いな気がしてきました。


HASHTBL Fruits

TEXTBLOCK list_fruit
Apple
Orange
Melon
ENDTEXTBLOCK

DIM fruit_list[3]
Array = SPLIT(list_fruit,"<#CR>")
FOR i=0 TO LENGTH(Array)-1
  fruit_list[i] = Array[i]
  PRINT "fruit_list["+i+"] = "+fruit_list[i] // 確認用
NEXT

fruit_Number = "100" //適当な数字
Fruits[GetIdx("Apple", fruit_Number)] = "ふじ"
PRINT Fruits[GetIdx(fruit_list[0], fruit_Number)] // ふじ と表示される
Fruits[GetIdx(fruit_list[0], fruit_Number)] = "紅玉"
PRINT Fruits[GetIdx(fruit_list[0], fruit_Number)] // 紅玉 と表示される



FUNCTION GetIdx(kind, index)
  RESULT = kind + CHR(0) + index // 絶対に使わない文字を区切り文字にする
FEND

No.1165 2021/02/11(Thu) 10:50:48

Re: EVALで値の代入したい / cho
しゅんさんありがとうございます。

EVAL(fruit_list[0]+"[fruit_Number] := <#DBL>紅玉<#DBL>")
この囲み方、覚えておきます。ホント惜しかった。でも重ね掛けに視点が移っていたので、気が付くのに時間がかかったか、あきらめていたかもです。助かりました。

Raynaさんありがとうございます。

いただいたコードを実行してみました。
ふじ という変数に紅玉が入っているのを確認しました。
外向きに探索という表現は初耳でわかりませんでしたが、調べてみます。
盲点になりそうな点を教えていただきありがとうございます。

EVALで代入できることがわかったので、幅が広がりそうです。
本当にやりたいことは、20個程度ある連想を、PUBLICを使わずに自作関数を通して更新していくことです。

と、返信を書いている間に、しゅんさんからそれらしい追加アイデアが!
さっそく試してみます。
取り急ぎ、お礼まで。

No.1166 2021/02/11(Thu) 11:21:21

Re: EVALで値の代入したい / Rayna
>>1166 cho さん

>> 外向きに探索という表現は初耳でわかりませんでしたが、調べてみます。

分かりづらかったかもしれないので補足
Eval に限った話ではないですが
UWSC では スクリプト、モジュール、関数に参照できる範囲があり 同名の 関数名, 変数名 をつけることが出来ます

Const, TextBlock, Public, Public HashTbl, Def_Dll, Procedure, Function がグローバル参照で
Dim, HashTbl はローカル参照です

Module m の Procedure p 内で 変数 m.v を呼ぼうとして Eval("v") とかすると
m.p() 内に 変数 v がなければ成功しますが あった場合 m.p() 内の v が優先されます
それを回避する為に明示しないと駄目な場合があるよって話でした

詳しくはプログラミングにおけるスコープという概念を調べてください
どこからならどの変数を参照できるか等確かめてみてもいいかもしれません

//| サンプル |//////////

Public vp = "スクリプトのグローバル変数"
Dim v = "スクリプトのローカル変数"

m.p()

Procedure p()
 Dim v = "モジュール外関数のローカル変数"
FEnd

Module m
 Public vp = "モジュールのグローバル変数"
 Dim v = "モジュールのローカル変数"
 Procedure p()
  // 変数は Global が使えない
  Dim v = "モジュール内関数のローカル変数"
  Print v // Eval("v")
  Print This.v // Eval("This.v")
 FEnd

 Procedure p2()
  p() // m.p()
  m.p() // m.p()
  This.p() // m.p()
  Global.p() // p()
 FEnd
EndModule

No.1167 2021/02/11(Thu) 13:00:39

Re: EVALで値の代入したい / cho
しゅんさんありがとうございます。
残念ながら、私の力量では希望の処理をさせることができませんでした。
Fruits[GetIdx(fruit_list[0], fruit_Number)] = "紅玉"
しかし、このような形で、配列に関数を書くことができることを学びました。
アドバイスありがとうございます。

今一度、やりたいことを整理したので、何か良いヒントがあればお願いします。
EVALは使ったことがなく、苦肉の策でしたのでこだわりはありません。
やりたいことは、たぶん仕様的に無理かもしれないと考えていますが、
最悪、連想を宣言した関数内でFORをさせることは出来そうです。
同じ処理が何度か出てくるのでそのたびに書くと無駄にコードが長くなるので
少しでも見やすくできればと考えています。


HASHTBL Apple // 連想配列が20個程度ある
HASHTBL Orange
HASHTBL Melon

TEXTBLOCK list_fruit
Apple
Orange
Melon
ENDTEXTBLOCK

DIM fruit_list[3]
Array = SPLIT(list_fruit,"<#CR>")
FOR i=0 TO LENGTH(Array)-1
  fruit_list[i] = Array[i]
  PRINT "fruit_list["+i+"] = "+fruit_list[i] // 確認用
NEXT

fruit_Number = "100" //適当な数字
Apple[fruit_Number] = "ふじ"
Orange[fruit_Number] = "甘夏"
PRINT Apple[fruit_Number] // = ふじ と表示される
PRINT Orange[fruit_Number] // = 甘夏 と表示される

// この部分を別関数にしてFORで回したい(fruit_Numberは固定です) ////////
  EVAL(fruit_list[0]+"[fruit_Number] := <#DBL>つがる<#DBL>")
  EVAL(fruit_list[1]+"[fruit_Number] := <#DBL>清見<#DBL>")
///////////////////////////////////

PRINT Apple[fruit_Number] // = つがる と表示される
PRINT Orange[fruit_Number] // = 清見 と表示される

//処理ここまで

  //自作関数の処理 ※イメージなので動作しません
   // 連想を引数にすると解決できますが、20個ぐらい書くので、リスト化したものでシンプルにしたい
   // 連想をPUBLICするとこの問題は解決できますが、PUBLICしたくない
  PROCEDURE value_Update(Var fruit_list[],fruit_Number)
   // New_valueは外部データから取得するため、この関数内のコードは少し長くなります。
   FOR i=0 TO LENGTH(fruit_list)-1
    EVAL(fruit_list[i]+"[fruit_Number] := New_value")
   NEXT
  FEND

// 何かアイデアやヒントがあればぜひお願いします。

No.1168 2021/02/11(Thu) 13:28:08

Re: EVALで値の代入したい / cho
Raynaさんありがとうございます。

サンプルを動かして、コードの流れと結果を見比べてみました。
まだ、Evalの振る舞い(?)を理解できていませんが、

MODULEを使った場合のスコープについては理解が進んだような気がします。
特に、今回のヒントで、
「連想をPUBLICしたくないけど、別関数の処理結果で値を変えたい」というわがままは、
連想を宣言した処理をまるごとMODULEで括ってしまえば、
MODULE内で、PUBLICを宣言することで解決できそうな気がしています。

今から、仕事で少し外出してきますが、帰宅後色々試してみます。
スコープという視点、貴重なヒントになりました。ありがとうございます。

No.1169 2021/02/11(Thu) 13:55:13

Re: EVALで値の代入したい / stuncloud
連想配列ではなく二次元配列を使うという案

const lists = 3 // リストの数 (20個あるなら20)
const items = 200 // 最大アイテム数

// リスト一覧 ※ 必ず連番にしていく
const Apple = 0
const Orange = 1
const Melon = 2

dim fruit_list[lists - 1][items - 1]


fruit_Number = 100

fruit_list[Apple][fruit_Number] = "ふじ"
fruit_list[Orange][fruit_Number] = "甘夏"

print fruit_list[Apple][fruit_Number]
print fruit_list[Orange][fruit_Number]

procedure value_Update(var fruit_list[], fruit_Number)
 for i = 0 to length(fruit_list) - 1
  New_value = New_value取得処理()
  fruit_list[i][fruit_Number] = New_value
 next
fend


fruit_list[Apple][0] みたいな書き方ができるので区別はしやすいかな?という感じでやっています
evalも使いませんし
ただ、そのためのcosnt定義でうっかりするとバグになっちゃうしあまり良い解決案ではないですね

# enum欲しくなりますね

No.1170 2021/02/11(Thu) 14:07:43

Re: EVALで値の代入したい / cho
stuncloudさんありがとうございます。

希望通りの処理ができました。
2次元配列が呼出時に連想配列と同じ書き方ができるというのも、私にはとても新鮮な使いかたで感動しました。
cosntを超えるとバグるかもしれないという点も考慮してitemsを調整してみます。

全体処理に組み込んだ時に希望通りの動作をしてくれるように頑張ります。

しゅんさん、 Raynaさん、stuncloudさん改めてありがとうございます。
いただいたアイデアやヒントはどれも、今後に役立たせていけそうです。

なるべく自分で解決する努力をしますが、行き詰った時にアドバイスを求めるかもしれません。
また見かけた時は何卒よろしくお願いします。

No.1171 2021/02/12(Fri) 07:40:04

Re: EVALで値の代入したい / しゅん
// もう不要かもしれませんが、こんな感じ?


HASHTBL Fruits // 連想配列はこれ一つでOKです。CONST/fruit_listを20個作ってください

// Const良いですね。この方式の場合、ユニークなら連番でなくても良いです。
Const Apple = 100
Const Orange = 200
Const Melon = 300
DIM fruit_list[] = Apple, Orange, Melon

fruit_Number = "100" //適当な数字
Fruits[_I(Apple, fruit_Number)] = "ふじ" // Apple[fruit_Number]をこう書き換えます。以下同じ
Fruits[_I(Orange, fruit_Number)] = "甘夏"
PRINT Fruits[_I(Apple, fruit_Number)] // = ふじ と表示される
PRINT Fruits[_I(Orange, fruit_Number)] // = 甘夏 と表示される

value_Update(Fruits, fruit_list, fruit_Number)

PRINT Fruits[_I(Apple, fruit_Number)] // = つがる と表示される
PRINT Fruits[_I(Orange, fruit_Number)] // = 清見 と表示される



FUNCTION _I(kind, index) // GetIdxは入力が面倒なので変えました
  RESULT = kind + CHR(0) + index // 絶対に使わない文字を区切り文字にする
FEND


TEXTBLOCK list_data
紅玉
清見
マスクメロン
つがる
ENDTEXTBLOCK

PROCEDURE value_Update(var fruits[], fruit_list[], fruit_Number) // fuit_listは参照のみなのでvar不要
 DIM datas = SPLIT(list_data, "<#CR>")
 FOR i=0 TO LENGTH(datas)-1
  fruits[_I(fruit_list[i Mod 3], fruit_Number)] = datas[i]
 NEXT
FEND

No.1173 2021/02/12(Fri) 12:10:56

Re: EVALで値の代入したい / cho
しゅんさん気にかけていただいてありがとうございます。

コード拝見させていただきました。

連想配列を一つにすることで参照渡しで更新できるのはとても便利だと感じました。

連想配列を多次元(例:連想名[キー][][]][]など)にできないかと数日間悩んでいたのを憶えています。
この書き方を使えるようになれば、いろんな問題が解決できそうです。

今回はMODULEと2次元配列で私の問題を解決できそうですが、
誰か(未来の私かもしれない)の参考になると思います。
素晴らしいヒントとコードをありがとうございます。

No.1175 2021/02/12(Fri) 17:50:06

Re: EVALで値の代入したい / stuncloud
> 連想配列を多次元
SafeArrayを使えば連想配列で個別に配列を持たせることも可能です

hashtbl h

h["hoge"] = split("foo bar baz") // splitでSafeArrayにする
print h["hoge"][0] // foo

h["fuga"] = safearray(0, 9) // 長さ10の空の配列
h["piyo"] = safearray(0, 9, 0, 2) // 二次元配列もできる

さらにさらに
変数に連想配列のようにキーと値のペアを保持できるものを代入したい、という場合はScripting.Dictionaryが使えます
(値の出し入れがメソッド経由になるのでちょっと書くのが手間になりますが、なかなか便利です)

h["d"] = createoleobj("Scripting.Dictionary")
h["d"].Add("foo", "FOO") // foo というキーに対して FOO という値をセット
print h["d"].Item("foo") // FOO

No.1176 2021/02/13(Sat) 11:31:46

Re: EVALで値の代入したい / cho
stuncloudさんありがとうございます。

連想配列も多次元にできるのですね。
配列を勉強していた時に、とあるブログで
・連想配列は多次元配列では使えないのでありません。
という一文を読んで、鵜呑みにしていました。お恥ずかしいです。

SafeArrayは戻り値を配列で受ける時だけ使っていました。
SafeArrayの公式ヘルプを読みました。引数の意味と2次元まで作成できる点、理解しました。

恥をかいたついでに、無知を披露してしまいますが、
多次元の連想配列に代入する書き方を教えてください。
1時間程度彷徨いましたが、ヒントになる記事を見つけることができませんでした。
通常の多次元と同じ書き方でSyntaxErrorが出ます。
たぶん、とても簡単なことだと思うのですが・・・

DIM v[1][1]

v[0][0] = "value" // 通常の2次元はこの書き方で代入できる
PRINT v[0][0]

hashtbl h
h["hoge"] = split("foo bar baz") // splitでSafeArrayにする
print h["hoge"][0] // foo

h["hoge"][0] = "f002" // 同じ書き方でもSyntaxErrorがでる
print h["hoge"][0]



Dictionaryも初耳でしたので、調べていました。
COMオブジェを経由して使える連想配列という認識を得ました(誤解してるかもですが)
こんなこともできるのか。と、改めてUWSCの魅力を感じていました。
そして、ここで回答をいただくたびに新しい言葉を教えてもらって感謝しています。

No.1177 2021/02/13(Sat) 16:42:51

Re: EVALで値の代入したい / stuncloud
> h["hoge"][0] = "f002" // 同じ書き方でもSyntaxErrorがでる
うわあ、確認不足でしたごめんなさい
これはおそらく連想配列の要素にインデックス指定して代入、をUWSCが許容していないということだと思います
値を読むだけならOKだけど代入は無理ということになりますね
つまりこの方法は使えない…ので忘れてください…ほんとすいません…

> COMオブジェを経由して使える連想配列という認識
そんな感じでOKです
例えば連想配列を関数の戻り値にしたいけど、仕様上できないので代わりにScripting.Dictionaryを使う
みたいな感じで使うことがあったりなかったりします

No.1179 2021/02/13(Sat) 18:57:59
ライセンスキーの確認方法 / orey
有料版のproをメインPCとサブ機で使っていましたがメインPCが逝ってしまい新調しました。
新しくインストールしたのですがライセンスキーがわからなくなってしまいました。
サブ機の方で使っているのでライセンスキーの確認をしたいのですが、確認方法をご存じの方がいらっしゃいましたら教えていただけませんでしょうか。
よろしくお願いいたします。

No.1172 2021/02/12(Fri) 10:42:24

Re: ライセンスキーの確認方法 / しろまさ
すなわちそれはUWSCに限らず、他人のライセンスキーを奪う方法と同じですよね?
モラル的にアウトなので自分で調査しきれないなら諦めてください。

No.1174 2021/02/12(Fri) 13:21:25

Re: ライセンスキーの確認方法 / 諦めないで
おそらくベクターで購入していると思いますが、その場合は以下の方法で確認できます。
1) ベクターPCショップ
  https://pcshop.vector.co.jp/service/
2) 右上にある[ご注文の確認・受取はこちら]の青いボタン
3) [購入履歴の確認]ボタン
4) ログイン
  ※ログイン情報が分からない場合は下部のリマインダーを使う
5) [最近半年分の注文] --> [全て表示]に変更
6) [ライセンスキーを表示]ボタン

無いとは思いますが、他の購入サイトであっても購入履歴から確認できると思います。

No.1178 2021/02/13(Sat) 16:47:48
同じアプリを区別 / sousou
お世話になります。
ソフトを1度起動すると、1つも画面が出てきますが、再度、起動すると、同じ画面がまた出ます、そこでこの二つを区別したいのですが、なにかしらの方法はございますでしょうか、getidでは、当然、同じものしか取得できません。
getid("無題 - メモ帳", "Notepad")

No.1159 2021/02/09(Tue) 12:06:09

Re: 同じアプリを区別 / Rayna
>>1159 sousou さん

・Execで起動時のIdを取る
 一番確実でローコスト, 安定性もある
 一部取れないウインドウとかは
  idWnd = Status(Exec("app.exe"), ST_PARENT)
 とかで取れる場合がある

・GetId, Exec を使わない場合
 GetAllWinを使うことになりますが実行コスト高めです

 ・GetAllWinで差分を獲得する
  Dim saIds, saNewIds, idWnd
  SendStr(Exec("notepad.exe"), "1つめ")
  saIds = GetNewWin() // すべてのウインドウ
  SendStr(Exec("notepad.exe"), "2つめ")
  saNewIds = GetNewWin(saIds) // すべてのウインドウ - saIds

  idWnd = GetIdByIdList(saIds, EMPTY, "Notepad", 1) // 1つめ
  SendStr(idWnd, "<#CR>1つめに追記")
  idWnd = GetIdByIdList(saNewIds, EMPTY, "Notepad", 1) // 2つめ
  SendStr(idWnd, "<#CR>2つめに追記")

 ・GetAllWinのフィルター関数を作る
  // ウインドウクラスが "Notepad" And プライマリモニタに表示されてるウインドウ
  For idWnd In GetIdsByEval("Status(<ID>, ST_CLASS)=<#DBL>Notepad<#DBL> And Status(<ID>, ST_MONITOR)=0")
   Print GetStr(idWnd, 1)
  Next


// 関数サンプル
// GetAllWinで差分を獲得する
Function GetNewWin(saOldWins=)
 GetAllWin()
 Select VarType(saOldWins)
 Case VAR_ARRAY Or VAR_VARIANT
  Dim aNewIds[Length(saOldWins)+Length(ALL_WIN_ID)]
  Dim sOldWins = " "+Join(saOldWins, " ")+" "
  Dim i, j=0
  For i = 0 To Length(ALL_WIN_ID)-1
   If Pos(" "+ALL_WIN_ID[i]+" ", sOldWins)<>0 Then Continue
   aNewIds[j] = ALL_WIN_ID[i]
   j = j + 1
  Next
  RESULT = Slice(aNewIds, 0, j-1)
 Default
  RESULT = Slice(ALL_WIN_ID)
 SelEnd
FEnd
Function GetIdByIdList(saIds, sTitle=, sClass=, nOffset=0)
 RESULT = -1
 nOffset = Int(nOffset)
 If VarType(saIds)<>(VAR_ARRAY Or VAR_VARIANT) Then Exit
 If Length(sTitle+sClass)=0 Then Exit
 If nOffset=0 Then nOffset=1
 Dim idWnd
 For idWnd In saIds
  IfB VarType(sTitle)<>VAR_EMPTY Then
   If Pos(sTitle, Status(idWnd, ST_TITLE))=0 Then Continue
  EndIf
  IfB VarType(sClass)<>VAR_EMPTY Then
   If Pos(sClass, Status(idWnd, ST_CLASS))<>1 Then Continue
  EndIf
  RESULT = idWnd
  nOffset = nOffset - 1
  If nOffset=0 Then Exit
 Next
FEnd

// GetAllWinのフィルター関数を作る
Function GetIdsByEval(sEval="")
 GetAllWin()
 Dim idWnd, i=-1, aIds[i]
 sEval = Replace(sEval, "<ID>", "idWnd")
 IfB Length(sEval)=0 Then
  RESULT = Slice(ALL_WIN_ID)
  Exit
 EndIf
 For idWnd In ALL_WIN_ID
  Try
   If Eval(sEval) Then
    i = i + 1
    Resize(aIds, i)
    aIds[i] = idWnd
   EndIf
  Except
  EndTry
 Next
 RESULT = Slice(aIds, 0, i)
FEnd

No.1160 2021/02/09(Tue) 15:42:16

Re: 同じアプリを区別 / sousou
Rayna様、ありがとうございます、Execで起動時のIdは、-1とか、0で区別できませんでしたが、GetAllWinは、不安定ながら確認できました。
コスト高めな関数までご提示いただき、今後の参考にさせていただきます、ありがとうございました。

 ・

No.1161 2021/02/09(Tue) 19:43:03

以下のフォームに記事No.と投稿時のパスワードを入力すれば
投稿後に記事の編集や削除が行えます。
200/200件 [ ページ : << 1 ... 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 >> ]

- HOME - お知らせ(3/8) - 記事検索 - 携帯用URL - フィード - ヘルプ - メール - 環境設定 -

- Skin: Modern v2.0 - Author: ロケットBBS -

Rocket Board Type-X (Free) Rocket BBS