|
|
2017/10/25(Wed) 23:29:23|NO.81675
過去ログを参照して、7-zip32.dllを
#uselib "7-zip32.dll"
#cfunc SevenZip "SevenZip" int, str, var, int
#func SevenZipSetBackGroundMode "SevenZipSetBackGroundMode" int
のように宣言して使っているのですが、ファイル名に機種依存文字(ハートマークなど)を含む
ファイル名を渡すとエラーになってしまい困ってます。
文字列としてはUTF16で受け取っているのをDrawTextWで表示して確認済ですが、
SevenZipにどう渡してもエラーになってしまいます。
よろしくお願いします。
|
|
2017/10/25(Wed) 23:56:39|NO.81676
私は7-zip32.dllを知らないので的の外れた回答だったらすみません
解凍部分を含めた関数定義以外の部分も貼っていただければ一発で回答できたかもしれませんが…
SevenZipの第二引数のstrがファイル名を渡しているとして、そこをsptrやintに変え、
UTF-16な文字列が入った変数をvarptrを使い関数に渡したらどうなるでしょうか
※もしかしたらSevenZipの第二引数をwptrに変えるだけで出来るかもしれません?
|
|
2017/10/27(Fri) 00:31:24|NO.81685
では、ソースです。
#include "gdi32.as"
#packopt name "ZipCleaner"
#packopt last "1"
#include "user32.as"
#module
#deffunc mesW var p1
p2.0=ginfo_cx,ginfo_cy,ginfo_winx,ginfo_winy
DrawTextW hdc,varptr(p1),-1,varptr(p2),0
mes : redraw 1
return
#global
#include "kernel32.as"
#define CP_UTF8 65001
#uselib "shell32.dll"
#func DragAcceptFiles "DragAcceptFiles" int,int
#func DragQueryFile "DragQueryFileA" int,int,int,int
;#func DragQueryFile "DragQueryFileW" int,int,int,int
#func DragQueryPoint "DragQueryPoint" int,int
#func DragFinish "DragFinish" int
#define WM_DROPFILES 0x0233
#uselib "7-zip32.dll"
#cfunc SevenZip "SevenZip" int, str, var, int
#func SevenZipSetBackGroundMode "SevenZipSetBackGroundMode" int
#define SIZE_MAX 4096
sdim filename, 260
sdim zipName, 256 * 2
sdim result, 32000
sdim selected
sdim del_filename
sdim attr
dim SIZE, 2
del_state = 0
SevenZipSetBackGroundMode( 0 )
oncmd gosub *OnDropFiles, WM_DROPFILES
DragAcceptFiles hwnd, 1
title "ウィンドウにZIPファイルをドロップしてください"
font "MS P 明朝", 12
button "削除", *del_item
py = ginfo_cy
mes ""
mes " Date Time Attr Size Compressed Name"
winobj "listbox", "", $200, $50000001 | $100000 | $200000 | $800, 620, 400
oListbox = stat
hListbox = objinfo(oListbox, 2)
GetStockObject 17
hFont = stat
sendmsg hListbox, $30, hFont
SelectObject hdc, hFont
stop
*OnDropFiles
hdrop = wParam
DragQueryFile hdrop, -1, 0, 0
ndrop = stat
syscolor 5 : boxf
syscolor 8 : pos 0,py
DragQueryFile hdrop, 0, varptr(filename), 260
mes getpath(filename, 8)
;mesW filename
mes " Date Time Attr Size Compressed Name"
gosub *ziplist
; ドロップファイル情報をクリア (これをしないとメモリリークになる)
DragFinish hdrop
return
*ziplist
; リストボックス内のアイテム削除
gosub *del_all_item
; 拡張子判別
zipExt = getpath(filename, 2)
if zipExt != ".zip" : dialog "ZIPではありません" :return
zipName = filename
result = ""
lstCmd = "l -r \"" + zipName + "\""
if SevenZip( hwnd, lstCmd, result, 32000 ) {
dialog "取得失敗"
return
}
notesel result
idx = 0
sw = 0
repeat notemax
noteget b, idx
idx++
if (instr(b, 0, "------------------- ") = 0) : sw ^= 1 : continue
if sw = 0 : continue
sendmsg hListbox, $180, , b
GetTextExtentPoint32 hdc, b, strlen(b), varptr(SIZE)
if SIZE > maxSIZE {
sendmsg hListbox, $194, SIZE + 3
maxSIZE = SIZE
}
loop
noteunsel
return
*del_all_item
sendmsg hListbox, $18B
itemNum = stat
n = itemNum - 1
repeat itemNum
sendmsg hListbox, $187, n
if stat : sendmsg hListbox, $185, 0, n
sendmsg hListbox, $182, n
n--
loop
return
*del_item
sendmsg hListbox, $18B
itemNum = stat
n = itemNum - 1
repeat itemNum
sendmsg hListbox, $187, n
if stat {
sendmsg hListbox, $189, n, varptr(selected)
attr = strmid(selected, 20, 5)
del_filename = strmid(selected, 53, 256)
sendmsg hListbox, $185, 0, n
if instr(attr, 0, "D") = 0 : continue
gosub *del_file
if del_state = 0 {
sendmsg hListbox, $182, n
}
}
n--
loop
stop
*del_file
delCmd = "d -hide \"" + zipName + "\" \"" + del_filename + "\""
del_state = SevenZip( hwnd, delCmd, result, 32000 )
if del_state : dialog result
return
zipファイルの中身の一部分だけを削除するツールです。
機種依存文字はSJIS扱いだと"?"に化けるので、7zipのeコマンドやlコマンドは
補完が利いて動作しますが、aコマンドやdコマンドだとエラーになってしまいます。
コメントアウトしているDragQueryFileWの方を有効にしてやると、
UTF16でファイル名が取得できますが、ご提案いただいた方法では
解決できませんでした。
| |
|
2017/10/27(Fri) 03:41:06|NO.81688
7-zip32.dllって割と面倒ですね…
Windowsで言うUnicodeはUTF-16LEな文字列の事を指しますが、7-zip32.dllはUTF-8文字列の事をUnicodeと呼んでいます。
間違いということでは無いのですが、非常にややこしいです。
UTF-8文字列はHSP3utfランタイムを使えば簡単に扱えるのですが、逆にそれを使わないと非常に面倒です。
途中までやりましたが諦めました。
以下はHSP3utfランタイムを使った例です。
…
…とここまで書いて、どうもHSP3utfランタイム側のバグで動作が不安定なので標準ランタイムでやってやりました
二度とやりたくありません
#include "gdi32.as"
#packopt name "ZipCleaner"
#packopt last "1"
#include "user32.as"
#module
#deffunc mesW var p1
p2.0=ginfo_cx,ginfo_cy,ginfo_winx,ginfo_winy
DrawTextW hdc,varptr(p1),-1,varptr(p2),0
mes : redraw 1
return
#global
#include "kernel32.as"
#define CP_UTF8 65001
#uselib "shell32.dll"
#func DragAcceptFiles "DragAcceptFiles" int,int
#func DragQueryFile "DragQueryFileW" int,int,int,int
#func DragQueryPoint "DragQueryPoint" int,int
#func DragFinish "DragFinish" int
#define WM_DROPFILES 0x0233
#uselib "7-zip32.dll"
#cfunc SevenZip "SevenZip" int, str, var, int
#func SevenZipSetBackGroundMode "SevenZipSetBackGroundMode" int
#define SIZE_MAX 4096
//文字コード変換周りで使います
#include "encode.as"
sdim filename, 260
sdim zipName, 256 * 2
sdim result, 32000
sdim selected, 1024
sdim del_filename
sdim attr
sdim tempString, 2048 //UTF16やUTF8を渡したり受け取るときのバッファ
dim SIZE, 2
del_state = 0
SevenZipSetBackGroundMode( 0 )
oncmd gosub *OnDropFiles, WM_DROPFILES
DragAcceptFiles hwnd, 1
title "ウィンドウにZIPファイルをドロップしてください"
font "MS P 明朝", 12
button gosub "削除", *del_item
py = ginfo_cy
mes ""
mes " Date Time Attr Size Compressed Name"
//winobj "listbox", "", $200, $50000001 | $100000 | $200000 | $800, 620, 400
//oListbox = stat
CreateWindowExW $200, "listbox", "", $50000001 | $100000 | $200000 | $800, ginfo_cx, ginfo_cy, 620, 400, hwnd, 0, 0 ,0
hListbox = stat
GetStockObject 17
hFont = stat
sendmsg hListbox, $30, hFont
SelectObject hdc, hFont
stop
*OnDropFiles
hdrop = wParam
DragQueryFile hdrop, -1, 0, 0
ndrop = stat
syscolor 5 : boxf
syscolor 8 : pos 0,py
DragQueryFile hdrop, 0, varptr(tempString), 1023
//DragQueryFileが返す文字列はUTF-16LEの為UTF-8に変換
WideCharToMultiByte 65001, 0, varptr(tempString), -1, varptr(filename), 260, 0, 0
//filenameはHSP標準のS-JISではなくUTF-8のまま格納されています 注意
mes getpath(utf8n2sjis(filename), 8)
;mesW filename
mes " Date Time Attr Size Compressed Name"
gosub *ziplist
; ドロップファイル情報をクリア (これをしないとメモリリークになる)
DragFinish hdrop
return
*ziplist
; リストボックス内のアイテム削除
gosub *del_all_item
; 拡張子判別
zipExt = getpath(utf8n2sjis(filename), 2)
if zipExt != ".zip" : dialog "ZIPではありません" :return
zipName = filename
result = ""
//lstCmd = "l -r \"" + zipName + "\""
// -sccスイッチを指定しないと何故かS-JISとしてファイル名を解釈したUTF-8文字列を返してくる
// sjisとUTF-8では英数字記号の部分が共通なので「l -sccUTF-8 -r 」などはUTF-8に変換する必要はない
lstCmd = "l -sccUTF-8 -r \""+ zipName + "\""
if SevenZip( hwnd, lstCmd, result, 32000 ) {
dialog "取得失敗"
return
}
notesel result
idx = 0
sw = 0
repeat notemax
noteget b, idx
idx++
if (instr(b, 0, "------------------- ") = 0) : sw ^= 1 : continue
if sw = 0 : continue
//bにはUTF-8な文字列が入っているがこれをUTF-16LEに変換しないと
//ListBoxで化けてしまう
MultiByteToWideChar 65001, 0, varptr(b), -1,varptr(tempString), 1023
SendMessageW hListbox, $180, 0, varptr(tempString)
GetTextExtentPoint32 hdc, b, strlen(b), varptr(SIZE)
if SIZE > maxSIZE {
sendmsg hListbox, $194, SIZE + 3
maxSIZE = SIZE
}
loop
noteunsel
return
*del_all_item
sendmsg hListbox, $18B
itemNum = stat
n = itemNum - 1
repeat itemNum
sendmsg hListbox, $187, n
if stat : sendmsg hListbox, $185, 0, n
sendmsg hListbox, $182, n
n--
loop
return
*del_item
sendmsg hListbox, $18B
itemNum = stat
n = itemNum - 1
repeat itemNum
sendmsg hListbox, $187, n
if stat {
//sendmegだとご丁寧にsjisに変換してくれるが文字が化けるため
SendMessageW hListbox, $189, n, varptr(tempString)
//ListboxはUnicode版のCreateWindowExされているのでUTF-16LE文字列を返す
//selectedやdel_filenameにはUTF-8文字列が入るが+結合子やstrmidなどはそのまま使える
//dialogやmesで内容を確認したいときはutf8n2sjisを使おう
WideCharToMultiByte 65001, 0, varptr(tempString), -1, varptr(selected), 1023, 0, 0
attr = strmid(selected, 20, 5)
del_filename = strmid(selected, 53, 256)
//dialog ""+utf8n2sjis(del_filename) //unicodeでしか表現できないものは?になる
sendmsg hListbox, $185, 0, n
if instr(attr, 0, "D") = 0 : continue
gosub *del_file
if del_state = 0 {
sendmsg hListbox, $182, n
}
}
n--
loop
return
*del_file
delCmd = "d -sccUTF-8 -hide \"" + zipName + "\" \"" + del_filename + "\""
del_state = SevenZip( hwnd, delCmd, result, 32000 )
if del_state : dialog result //私のDLしたdllだと削除に失敗しても0が帰る…
return
一部UTF-8文字列のままHSPの標準関数を使っていますが、問題はないはずです。
UTF-8はバイト単位のキャラクターセットで終端nullとして扱う分にはSJISと同じだからです。
(逆にUTF-16は2バイト単位で見る必要があり非常に面倒です プリミティブ型しか無いような言語で扱うものではない…)
| |
|
2017/11/3(Fri) 00:40:58|NO.81768
ご教示、ありがとうございました。
うちの環境ではなぜか-sccUTF-8を指定すると正常に動作しないようです。
問題点の切り分けには時間がかかりそうなので、一旦解決済みとさせていただきます。
|
|