tomatomax.net

Every rule has its exception.

Archive for the Delphi Category

学習リモコンで送信

先日に引き続いてBUFFALOのPC-OP-RS1を利用したデータ送信(参考:スーの道具箱)。シリアル通信にはDelphi 4用通信コンポーネント(Windows95/98/Me / プログラミング)を使用。送信部分自体は結構前にできていたのだけれども、いろいろ機能を追加してたら時間がかかってしまった。まだまだ作りかけなのだけれども。今後は、常駐させてタイマ機能つけたり、スキンで概観いじれるようにしたりするかも。

http://hp.vector.co.jp/authors/VA013135/guutara.zip

データの入力が面倒なのがきついなぁ。

学習リモコンで受信

BUFFALOのPC-OP-RS1を利用してデータを受信してみる(参考:スーの道具箱)。シリアル通信にはDelphi 4用通信コンポーネント(Windows95/98/Me / プログラミング)を使用。

受信してcsvに落とすプログラムhttp://hp.vector.co.jp/authors/VA013135/receive_rc.zip。まだその先の送信作ってないけど。

かなり適当な通信部分。

try
try
ReceiveForm := TReceiveForm.Create(Application);
ReceiveForm.rs232c.portname := COMCombo.Text;

if(not ReceiveForm.rs232c.rsopen)then Raise Exception.Create('error -- open');
if(not ReceiveForm.rs232c.rswritechar(Chr($72)))then Raise Exception.Create('error -- write');
if(not ReceiveForm.rs232c.rsreadchar(c))then Raise Exception.Create('error -- read');
if(c <> Chr($59))then Raise Exception.Create('error -- not Y($59)');
if(ReceiveForm.ShowModal = mrCancel)then Raise Exception.Create('cancel');
if(not ReceiveForm.rs232c.rsreadchar(c))then Raise Exception.Create('error -- read');
if(c <> Chr($53))then Raise Exception.Create('error -- not S($53)');

if(not ReceiveForm.rs232c.rsread(data, 240))then Raise Exception.Create('error -- read');
data[240] := #0;
if(not ReceiveForm.rs232c.rsreadchar(c))then Raise Exception.Create('error -- read');
if(c <> Chr($45))then Raise Exception.Create('error -- not E($45)');
ReceiveForm.rs232c.rsclose;

ListItem := DataListView.Items.Add;
ListItem.Caption := name;
ListItem.SubItems.Add(DataToStr(data));
except
on e: Exception do
MessageDlg(e.Message, mtError, [mbOK], 0);
end;
finally
ReceiveForm.Free;
end;

レジストリ

TRegistryクラスでサクサク。下はCOMポート一覧を取り出しているところ。

var
i: Integer;
reg: TRegistry;
st: TStringList;
begin
reg := TRegistry.Create;
st := TStringList.Create;
reg.RootKey := HKEY_LOCAL_MACHINE;
if(reg.OpenKey('\HARDWARE\DEVICEMAP\SERIALCOMM\', False))then
begin
reg.GetValueNames(st);
for i := 0 to st.Count - 1 do
begin
if(reg.GetDataType(st.Strings[i]) = rdString)then
COMCombo.Items.Append(reg.ReadString(st.Strings[i]));
end;
reg.CloseKey;
end;
st.Free;
reg.Free;

最前面に表示されているウィンドウかどうか調べる

GetWindowLong関数を使って、拡張ウィンドウスタイルを取得すればいいのかな。EnumWindowsあたりと組み合わせて、全てのウィンドウに対して調べてみたり。

if (GetWindowLong(Handle, GWL_EXSTYLE) and WS_EX_TOPMOST) = WS_EX_TOPMOST then
ListBox1.AddItem('OK', nil)
else
ListBox1.AddItem('NG', nil);

スーパーpre記法(シンタックス・ハイライト)を使ってみたかっただけでした><

TScrollBar.PageSize

スクロールボックスのサイズ。表示している割合を示すために使うプロパティ。

w := 639 - Panel.Width;
ScrollBarH.Max := w;
ScrollBarH.PageSize := w * Panel.Width div 639;

幅640の領域をパネルに表示するときの割合。パネルのサイズが640以上になるとまずいのでエラー処理を加える必要あり。

UDP送信

SOCK_DGRAMでソケットを作ったらsendto()でサクっと送信。

sock := socket(PF_INET, SOCK_DGRAM, 0);
sendto(sock, packet, 6 + 6 * 16, 0, addr, sizeof(addr));
closesocket(sock);

WOL用のマジックパケット送信プログラム作ってみました(http://hp.vector.co.jp/authors/VA013135/mpsend.zip)。

> mpsend.exe 192.168.0.255 12-34-56-78-90-AB

↑こんな感じで使用。とりあえずこれだけ。

UDP受信

socket関数の第二引数をSOCK_DGRAMにすること。あとはbind。

以下、受信して表示するだけのプログラム。

program receive;

{$APPTYPE CONSOLE}

uses
SysUtils,
Winsock;

procedure dump(b: array of byte);
var
i, size: Integer;
begin
size := Length(b);
Write('       +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +a +b +c +d +e +f');
for i := 0 to size - 1 do
begin
if(i mod 16 = 0)then
Write(#13#10 + Format('0x%.4x ', [i]));
Write(Format('%.2x ', [b[i));
end;
end;

var
wsa: TWSAData;
sock: TSocket;
addr: TSockAddrIn;
buf: array[0..6 + 16 * 6 - 1] of Byte;
begin
if(WSAStartup($0101, wsa) <> 0)then
raise Exception.Create('WSAStartup');
sock := socket(PF_INET, SOCK_DGRAM, 0);

addr.sin_family := AF_INET;
addr.sin_port := htons(2034);
addr.sin_addr.S_addr := INADDR_ANY;

bind(sock, addr, Sizeof(addr));
recv(sock, buf, 6 + 16 * 6, 0);

dump(buf);

closesocket(sock);
if(WSACleanup <> 0)then
raise Exception.Create('WSACleanup');
{$WARNINGS OFF}
if(DebugHook <> 0)then
Readln; // IDEでの起動時は一旦停止
{$WARNINGS ON}
end.

Winsockの初期化

いまさら感が否めないけれども、またネットワークをいじりたくなってきたので結構昔のソースを発掘。

uses
... , Winsock;

...

var
r: Integer;
WSAData: TWSAData;
version: WORD;
begin
// WinSockの初期化
version := $0002;
r := WSAStartup(version, WSAData); // Version 2.0
if(r <> 0)then
begin
version := $0101;
r := WSAStartup(version, WSAData);
if(r <> 0)then
raise Exception.Create('Winsockの初期化に失敗しました:') at @r;
end;
end;

終了時はWSACleanup()を忘れずに。

拡張子判定

文字列の終わりに拡張子が入っているかどうかをAnsiEndsTextで判定。

s := SaveDialog1.FileName;
if(not AnsiEndsText(s, '.ini'))then
s := s + '.ini';

シャングハイ

http://hp.vector.co.jp/authors/VA013135/shanguhai.zip

多少アップデートしたのをすっかり忘れてた。