記事カテゴリ

ユーザー機能


 2024年5月28日(火) 19:25 JST

[Delphi] コンポーネントを使用したらアドレス違反が...

  • 記事を友だちにメール
  • 印刷用ページ
  • 投稿者:
  • 表示回数
    6,424
コンポーネントを自身のプログラムに組み込んだら、アプリケーションの起動時または、追加したフォームの作成時に「アドレス違反が発生した。」ということはありませんか?こんな時、くろねこ製のコンポーネントだと、ふつうは真っ先にコンポーネントのバグを疑います。(またテスト漏れしてやがると、サポート掲示板にでも苦情を書き込んでやってください。)がしかし、ほかのプログラムでは正常に動いてるのに...
こんな時には、プロジェクトの設定を確認してください。プロジェクト|オプション|パッケージ の「実行時パッケージを使って構築」にチェックがついていませんか?このチェックが ON の場合には、パッケージ本体のファイルが必要になります。具体的にはアプリケーション実行時にパスの通ったディレクトリに、*.bpl ファイルが必要になります。

実行時パッケージを使って構築って?

実行時パッケージを使って構築を使うと DLL を使った時のように、重複するコードをプログラムの外に出すので EXE ファイルのサイズを小さくできます。実行時に BPL ファイルを読み込んでダイナミックにプログラムと結合してアプリケーションの動作に寄与します。このため実行時に参照できる状態にないと、アドレス違反が発生するのです。 小さいアプリケーションの場合には、実行時パッケージを使わない方がよいでしょう。EXE 一つで配布が完了するので、配布ファイルの管理が非常に楽になります。
ではいつ実行時パッケージを使った方がよいのでしょうか?それは、プログラムの配布サイズが企業ポリシーで制限されている場合や、頻繁に修正されるようなプログラムで修正される部分と修正されない部分を分けてしまう場合などがあります。大きなアプリケーションですと、サブシステム毎に分割を行うということもあるでしょう。
分割してしまうと、その実行時パッケージに修正を行った場合(機能拡張やバグ修正など)、にその実行時パッケージを配布すればよいので、配布するプログラムのサイズを大幅にカットできます。大企業やソフトハウスなどで遠隔地のパソコンに修正プログラムを配布しなければいけない場合には、時間の短縮にもなりますね。

[Delphi] フリガナを自動で入力する (for VCL.Net)

  • 記事を友だちにメール
  • 印刷用ページ
  • 投稿者:
  • 表示回数
    5,558

WM_IME_COMPOSITION メッセージが発生したときに、ImmGetCompositionString 関数を使ってFEP (IME など) が持つフリガナを取得します。

この例は、フリガナ機能付きコンポーネントの作成例です。
TEdit コンポーネントに KanaOut プロパティを追加しています。 この追加したプロパティに、Edit1(TEdit クラス) を設定すると、入力した文字のフリガナが Edit1.Text に入力されていきます。

unit KanaEdit;

interface

uses
  Windows, Messages, Classes, Graphics, Controls, StdCtrls;

type
  { TKanaEdit }
  TKanaEdit = class(TEdit)
  private
    FKanaOut: TEdit; // KanaOutプロパティ
  protected
    procedure SetKanaOut(AValue:TEdit);
    procedure WndProc(var Msg: TMessage); override;
  published
    // プロパティ
    ...
    property KanaOut: TEdit read FKanaOut write SetKanaOut;
    ...
  end;

procedure Register;

implementation

uses
  IMM;

procedure Register;
begin
  RegisterComponents('Samples', [TKanaEdit]);
end;

{*******************************************************************************
機能: カナ出力プロパティーセット
引数:
戻値:
*******************************************************************************}
procedure TKanaEdit.SetKanaOut(AValue: TEdit);
begin
  if (AValue = nil) or (AValue = Self) then
  begin
    FKanaOut := nil;
  end
  else
  begin
    FKanaOut := AValue;
  end;
end;

{*******************************************************************************
機能: メッセージ処理
引数:
戻値:
*******************************************************************************}
procedure TKanaEdit.WndProc(var Msg: TMessage);
var
  imc: HIMC; // IMEのコンテキストを格納
  sbKana: StringBuilder;
  nSize: Integer;
begin
  if (FKanaOut <> nil) then
  begin
    if (Msg.Msg = WM_IME_ENDCOMPOSITION) then
    begin
      imc := ImmGetContext(Handle);
      case Msg.Msg of
        WM_IME_ENDCOMPOSITION:
        begin
          // 変換結果の「読み」を取得
          nSize := ImmGetCompositionString(imc, GCS_RESULTREADSTR, nil, 0);
          sbKana := StringBuilder.Create;
          sbKana.Length := nSize;
          ImmGetCompositionString(imc, GCS_RESULTREADSTR, sbKana, nSize+1);
          ImmReleaseContext(Handle, imc);
          // 更新後文字列作成
          FKanaOut.Text := FKanaOut.Text + sbKana.ToString;
        end; // WM_IME_ENDCOMPOSITION
      end; // case
    end;  // if
  end;  // if
  inherited;
end;
end.

[Delphi] 入力禁止中に発生したユーザによる入力の消去

  • 記事を友だちにメール
  • 印刷用ページ
  • 投稿者:
  • 表示回数
    6,829

ある特定の処理実行中は、フォームやボタンの Enabled プロパティを False に設定し、2度同じ処理を実行されないようにしたりします。 しかし、Enabled が False でも True に変更する前にユーザがマウスクリックまたはEnterキーなどで処理をしていた場合、その操作に関連する処理は行われてしまいます。 今回はそのような問題への対策です。
以下の関数をボタンの Enabled を True にする際になどに実行します。

procedure PurgeMsgQueue(AHandle: HWND);
var
  Msg: TMsg;
begin
  // マウスのメッセージをキューから除去
  while PeekMessage(Msg, AHandle, WM_CLOSE, WM_QUIT, PM_NOREMOVE) do exit;
  while PeekMessage(Msg, AHandle, WM_DESTROY, WM_DESTROY, PM_NOREMOVE) do exit;
  while PeekMessage(Msg, AHandle, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE) do;
  // そのほかのメッセージをキューから除去
  while PeekMessage(Msg, AHandle, WM_CLOSE, WM_QUIT, PM_NOREMOVE) do exit;
  while PeekMessage(Msg, AHandle, WM_DESTROY, WM_DESTROY, PM_NOREMOVE) do exit;
  while PeekMessage(Msg, AHandle, WM_KEYDOWN, WM_KEYDOWN, PM_REMOVE) do;
end;

でも、この方法だと取り除きたいマウスとキーボードのメッセージの数だけ記述しないとダメなので、実用性はいかがなものだろうか?

別案として、別スレッドで処理するかマウスとキーボードの処理を別ウィンドウに処理させてしまう方法がある。

[Delphi] フォームの表示完了時

  • 記事を友だちにメール
  • 印刷用ページ
  • 投稿者:
  • 表示回数
    9,128

フォームを表示しているときに起こるイベントには「OnCreate」「OnShow」「OnActivate」などがありますが、表示し終わったときのイベントがありません。 これを取得するには「CMShowingChanged」メッセージをトラップします。(このメッセージを知るまでは、OnCreateで独自メッセージをポストし、トラップしてました。(^o^;))
実際のコードは以下のようになります。

type
  TForm1 = class(TForm)
private
  { Private 宣言 }
  (略)
  procedure CMShowingChanged(var Message: TMessage); message CM_SHOWINGCHANGED;
  (略)
end;

procedure TForm1.CMShowingChanged(var Message: TMessage);
begin
  inherited;  // 通常の CMShowingChagened をまず実行
  if (Visible) then
  begin
    Update; // 完全に描画
    // 実際の処理を記入
  end;
end;

[Delphi] 一回で深い階層のディレクトリを作成する

  • 記事を友だちにメール
  • 印刷用ページ
  • 投稿者:
  • 表示回数
    7,609

多階層のディレクトリを作成するには親ディレクトリから1つずつ作成していきます。
しかしこれでは面倒なので、ForceDirectories 関数を使って一発で作成することができます。
また、APIを使っても一発で作成することができます。
ForceDirectories は Delphi のヘルプに解説があるので、以下では API を使用する方法を解説します。

使用するAPIは、「MakeSureDirectoryPathExists」です。
この API と ForceDirectories との違いとしては、ForceDirectories は作成したいディレクトリを引数に指定するのに対し、 MakeSureDirectoryPathExists はファイル名を指定します。ディレクトリ名を指定したい場合は末尾に「\」を付けて渡す必要があります。

このAPIを使用するには以下の定義が必要です。

interface
  function MakeSureDirectoryPathExists(DirPath: LPCSTR): Bool; stdcall;
implementation
  function MakeSureDirectoryPathExists; external 'IMAGEHLP.DLL' name 'MakeSureDirectoryPathExists';

DirPath にはファイル名を指定します。 パスの最後のコンポーネントがファイル名ではなくディレクトリである場合、文字列の最後に円記号(\)を記述しなければなりません。 このAPIは失敗すると False を返します。 こんな感じになります

procedure TForm1.Button1Click(Sender: TObject);
begin
  if not MakeSureDirectoryPathExists(PChar('c:temp')) then
    raise Exception.Create('Cannot create c:temp');
end;

補足

  1. 設定可能なファイル名の長さは200-260文字程度みたいです。
  2. APIなので String を PWideChar または PChar で型キャストする必要があります。

参照

  1. Microsoft Developer Network Library

2015.11.20 MSDNのリンク先が変更になっていたので修正


サイトカレンダー

サイトカレンダーをスキップ

2023年 02月
«
»
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28

新着情報

記事 新着(24時間)

-

コメント 新着(2日)

-

トラックバック 新着(2日)

-

リンク 新着(2週)

新しいリンクはありません

ファイル (14日)