読者です 読者をやめる 読者になる 読者になる

伝説のツール「NotesPeek」をQtでリメイクする(その5・@式その2)

少し時間が空いたので、前回のおさらいをしておきます。

  1. @式(または@関数)はR4以前からある操作言語である。
  2. フォームは文書(Document)設計用の文書(Note)である。
  3. ウィンドウタイトルは、フォーム専用のフィールドである。
  4. @式は文字列として書かれ、バイナリとして保存される。

おおざっぱに言えば、このような感じです。

今回のリメイクツールでは、データベースのツリーアイテムを展開すると、すべての文書(Document)を取得して子アイテムとしてデータベースアイテムにぶら下がります。そして、各文書アイテムでは、NotesPeekのように、ウィンドウタイトルを表示させることにします。

ちなみに、NotesPeekではこのように文書(Document)を表示しています。

f:id:takahide-kondoh:20170504172520p:plain

もし表示されない場合は、メニュー「View−Options」としてこのダイアログを表示し、左ペインで「Notes」を選択し、右ペインで「Title」にチェックを付けると出てきます。

f:id:takahide-kondoh:20170504173545p:plain

この「Title」として表示されるのが「ウィンドウタイトル」になります。

前回も触れましたが、このウィンドウタイトルを取得するまでの手順もおさらいします。

  1. 文書(Document)を取得する。
  2. その文書の「Form」フィールドのテキスト値(フォーム名)を取得する。
  3. フォーム名に該当するフォーム(設計文書)を取得する。
  4. フォームの「ウィンドウタイトル」フィールドの値(=@式、バイナリ形式)を取得する。
  5. 文書(Document)を引数にして、ウィンドウタイトル式を評価(Evaluate)する。

それでは、順に関連するAPIを紹介していきます。文書の取得、テキスト値の取得は既出なので省略します。

それでは最初にフォーム文書(フォームNote)の取得です。フォームを含む設計文書の取得には、NIFFindDesignNoteを使用します。

#include <nif.h>

STATUS LNPUBLIC NIFFindDesignNote (DBHANDLE hFile, const char far *Name, WORD Class, NOTEID far *retNoteID);

hFileにデータベースハンドル、Nameに設計要素名、Classに文書クラスを与え、、retNoteIDに該当する設計要素文書のNoteIDが返ってきます。

次に、文書から@式を含む任意のフィールド値を取り出すには、NSFItemInfo関数を使います。

#include <nsfnote.h>

STATUS LNPUBLIC NSFItemInfo (
    NOTEHANDLE hNote
    , const char far *Name
    , WORD NameLength
    , BLOCKID far *retbhItem
    , WORD far *retDataType
    , BLOCKID far *retbhValue
    , DWORD far *retValueLength);

入力値として、hNoteに文書(Note)ハンドル、Nameにフィールド名、NameLengthにフィールド名の長さを指定します。

出力値としては、retbhItemにアイテム用のブロックID、retDataTypeにアイテムの型、retbhValueにアイテム値用のブロックID、retValueLengthにその長さが設定されます。

BLOCKIDとは、端的に言えば、文書内に格納されたデータへのハンドルです。@式の場合、アイテム値用のブロックIDをロックして、@式のバイナリデータを取得できます。ロックにはOSLockBlock、アンロックにはOSUnlockBlockを使います。

#include <pool.h>

#define OSLockBlock(type,blockid) ((type far *)(OSLock(char,(blockid).pool) + (blockid).block))

#define OSUnlockBlock(blockid) OSUnlockObject((blockid).pool)

取得したバイナリデータは、自前で用意したメモリに格納しておきます。自前でメモリを用意するにはOSMemAlloc、用意したメモリを解放するにはOSMemFreeを使います。メモリはハンドル形式なので、メモリ内を使う場合はブロックID同様ロックして使いますが、微妙に仕様が異なります。

#include <osmem.h>

STATUS LNPUBLIC OSMemAlloc (WORD BlkType, DWORD dwSize, DHANDLE far *retHandle);
STATUS LNPUBLIC OSMemFree (DHANDLE Handle);

void far * LNPUBLIC OSLockObject (DHANDLE Handle);
#define OSLock(blocktype,handle) ((blocktype far *) OSLockObject(handle))
#define OSUnlock(handle) OSUnlockObject(handle)
BOOL LNPUBLIC OSUnlockObject (DHANDLE Handle);

次回は@式に関するAPIを説明します。