Excelプレビュー表示時のメニューボタンを無効にするには?

解決


RU  2006-03-13 20:23:34  No: 20489

こんにちは。データをExcelに書き出して,まいと〜くFAXを用いてデータを送信しています。
送信前にExcel機能のプレビューを用いて印刷イメージを表示させようとしています。
ただこの時に【次ページ】,【前ページ】,【閉じる】ボタン以外を無効にしようと
考えているのですが,どうもうまくいかないのです。

いろいろ調べて下記のソースは組んでみたのですが知識不足の為,動かない原因が特定できていません。
API関数部分(SetTimer)の制御がうまくできてないのかなとは思っているんですが・・・
実際にpEnablePreviewTimer関数部分が走っていない現状です。
どなたか解決方法ご存じの方がいれば教えてもらえると幸いです。(長文申し訳ありません)

//===========================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  Excel: Variant;  //Excelアプリケーション
  xlsWkb: Variant; //Excelワークブック
  xlsWks: Variant; //Excelワークシート

begin
    ・
    Excel接続
    ・
    EnablePreview(xlsWks);
    ・
    Excel解放
    ・
end;

procedure TForm1.EnablePreview(xlsWks: Variant);
var
  TimerID: WORD;

  procedure pEnablePreviewTimer(hWnd: WORD; uMsg: WORD; idEvent: WORD; dwTime: WORD);stdcall;
  var
    i: Integer;
  begin

    hWnd := FindWindowExA(0, 0, 'XLMAIN', nil);
    hWnd := FindWindowExA(hWnd, 0, 'EXCELC', nil);

    for i := 1 to 9 do begin
      case i of
        2,3,4,5,6,8:EnableWindow(GetDlgItem(hWnd, i), False);
        else EnableWindow(GetDlgItem(hWnd, i), True);
      end;
    end;
  end;

begin

  TimerID := SetTimer(0, 0, 0, @pEnablePreviewTimer);
  try
    xlsWks.PrintPreview;
  finally
    KillTimer(0, TimerID);
  end;

end;


別案  2006-03-14 00:34:30  No: 20490

Excel PrintPreviewの表示は別スレッドで実行するべきでしょう。
Previewウィンドウが表示された時点でボタンを無効化すればOK。


Ru  2006-03-14 01:02:13  No: 20491

返信ありがとうございます。
あれから調べていまして,スレッドならもしかしてできるのかなと思い,
ソース組んでいました。もう少し頑張ってみます。ありがとございます。

スレッド初挑戦・・・


だいあん  2006-03-14 02:03:46  No: 20492

ボタンの無効化を別スレッドにした方が楽か…
type
  TThread1 = class(TThread)
  protected
   procedure Execute; override;
  end;
var
  Thread1: TThread1;

procedure TThread1.Execute;
var
  i, hW: Integer;
begin
  while not Terminated do begin
   hW := FindWindowExA(0, 0, 'XLMAIN', nil);
   hW := FindWindowExA(hW, 0, 'EXCELC', nil);
   if (hW <> 0)and(IsWindowVisible(hW)) then begin
    for i:=1 to 9 do
     case i of
      2,3,4,5,6,8: EnableWindow(GetDlgItem(hW, i), False);
      else         EnableWindow(GetDlgItem(hW, i), True);
     end;
    break;
   end;
  end;
  Terminate;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Excel: Variant;
  xlsWkb: Variant;
  xlsWks: Variant;
begin
  if not SUCCEEDED(CoInitialize(nil)) then exit;
  try
   try
    Excel := CreateOleObject('Excel.Application');
   except
    on EOleSysError do begin
     Excel := Null;
     exit;
    end;
   end;
   Excel.Visible := True;
   Excel.WorkBooks.Open('xlsファイル');
   xlsWkb := E_App.ActiveWorkbook;
   xlsWks := E_App.ActiveSheet;

   Thread1 := TThread1.Create(True);
   Thread1.FreeOnTerminate := True;
   Thread1.Resume;

   xlsWks.PrintPreview;
  finally
   Excel.Quit;
   Excel := Unassigned;
  end;
end;


Ru  2006-03-14 02:32:50  No: 20493

スレッドの使用で少し手こずっているのですが,
以下のソースで実行しデバックで追ったところ,
スレッド側のExcuteのルーチンが通っていないようなのです。
スレッドの使用で変な部分があるのであれば教えてもらえると幸いです。
スレッドの使用方法が根本的に間違えてる気もするんですが・・・(汗)
(Application.Processmessagesとか組み込んだりしましたが動きがまちまちだったので外しています。)
/////////////////////////////////////////////////////////////////
//=======================================================
//メイン側
//=======================================================
type
  TForm1 = class(TForm)
  ・
  private
  ・
  public
    ExcelWorkSheet: Variant;
  end;

procedure TForm1.EnablePreview(xlsWks: Variant);
var
  PreviewThread: ExcelPreviewThread;
  TimerID: WORD;

  procedure pEnablePreviewTimer(hWnd: WORD; uMsg: WORD; idEvent: WORD; dwTime: WORD);
  var
    i: Integer;

  begin

    hWnd := FindWindowEx(0, 0, 'XLMAIN', nil);
    hWnd := FindWindowEx(hWnd, 0, 'EXCELC', nil);

    for i := 1 to 9 do begin
      case i of
        4,5,6,7,9:EnableWindow(GetDlgItem(hWnd, i), False);
        else EnableWindow(GetDlgItem(hWnd, i), True);
      end;
    end;

  end;

begin
  
  ExcelWorkSheet := xlsWks;
  TimerID := SetTimer(0, 0, 10, @pEnablePreviewTimer);
  PreviewThread := ExcelPreviewThread.Create(True);
  try
    PreviewThread.Resume;
  finally
    PreviewThread.Free;
    KillTimer(0, TimerID);
  end;

end;
//=======================================================

//=======================================================
//スレッド側
//=======================================================
procedure ExcelPreviewThread.Execute;
begin

  Synchronize(PreviewStart);

end;

procedure ExcelPreviewThread.PreviewStart;
begin

  From1.ExcelWorkSheet.PrintPreview;

end;
//=======================================================


Ru  2006-03-14 04:09:51  No: 20494

あ、書いてる間に更新されてたのですね・・・
申し訳ありません。

だいあんさん、別案さんありがとうございます。m(_ _)m
再度試してきます。


Ru  2006-03-14 20:19:18  No: 20495

おはようございます。
だいあんさんの手法でプレビュー時の任意のボタンの無効化には成功しました。
ただ,プレビューまでに若干時間かかる為,メインExcelが確認ぐらい見えてしまいますので,
現在瞬間的にプレビュー画面が出るようにする、もしくはExcelの表示はせずに
Excelプレビューを出す方法を考えています。

質問ばかりで恐縮なのですが,また相談乗ってもらえると嬉しいです。
どなたかご存じの方がいれば教えていただけると幸いです。よろしくお願いし増す。

============================================================
今気になって考えいるところ
============================================================
プレビューする時はプレビュー指令より先に,
  Excel.Visible := True
はどうしてもいるのでしょうか?
delphi-MLの方に似たようなソースはあったのですが,
プレビュー指令後,画面に表示されずにプログラムが止まりました。
おそらくプレビュー中で固まっているのだとは思うんですが。

あとプレビュー中はSetTimerは効かないのでしょうか?
それとも使用方法が悪いのでしょうか・・・


きやすめ  2006-03-16 03:14:19  No: 20496

ワークシートも印刷プレビューも同じハンドル値のEXCELウィンドウに表示されているのだから、表示させなければ無理。
Excel.Visible := False;
にしておいて、別スレッドの中で
   .....
   hW := FindWindowExA(0, 0, 'XLMAIN', nil);
   if hW <> 0 then begin
     ShowWindow(hW, SW_SHOWNORMAL);
     SetForegroundWindow(hW);
   end;
   .....
と、表示させれば多少はマシ?気休め程度?


ちょいまち  2006-03-16 03:25:36  No: 20497

ちょっとダケヨ
>  .....
>  hW := FindWindowExA(0, 0, 'XLMAIN', nil);
   Sleep(500);
>  if hW <> 0 then begin
>    ShowWindow(hW, SW_SHOWNORMAL);
>    SetForegroundWindow(hW);
>  end;
>  .....


Ru  2006-03-16 04:15:09  No: 20498

きやすめさん。返信ありがとうございます。

教えていただいたソースで試したところ,かなり早くなりました。
若干見えるのは,使用に影響及ぼさない時間なのでこのまま様子見ようと思います。
APIにはまだまだ知らない関数が多かったので本当に助かりました。
SetTimerに関しては,プレビュー時にどうしても動かないので今回は使用しないようにします。
使用方法が間違っているおそれは大いにありえますが・・・。
別の機会にSetTimerを使うことが有れば再度勉強したいと思います。

今回の件に関しては,これで解決とさしていただこうと思います。
本当にありがとうございました。

//==============================================================================
//宣言
//==============================================================================
type
  TForm1 = class(TForm)
    ・
    ・
  private
    ・
    ・
    procedure EnablePreview(Excel, xlsWks: Variant);
  public
    { Public 宣言 }
  end;
//------------------------------------------------------------------------------

//==============================================================================
//Excelプレビュー
//==============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  Excel: Variant;
  xlsWkb: Variant;
  xlsWks: Variant;

begin
    ・
     Excel接続
  ・
        //プレビュー
        EnablePreview(Excel, xlsWks);

  ・
     Excel解放
  ・
end;
//------------------------------------------------------------------------------

//==============================================================================
//Excelプレビュー時,特定のボタン無効化(スレッドにて並列処理)
//==============================================================================
procedure TForm1.EnablePreview(Excel, xlsWks: Variant);
var
  TimerID: WORD;
begin

  Thread1 := Thread.Create(True);
  Thread1.FreeOnTerminate := True;
  Thread1.Resume;

  try
    xlsWks.Printpreview;
  finally
    Excel.Visible := False;
  end;

end;
//------------------------------------------------------------------------------

//==============================================================================
//スレッド側の処理
//==============================================================================
procedure Thread.Execute;
var
  hWnd: WORD;
  i: Integer;
begin

  while not Terminated do begin
    hWnd := FindWindowExA(0, 0, 'XLMAIN', nil);
    if hWnd <> 0 then begin
      Application.ProcessMessages;
      ShowWindow(hWnd, SW_SHOWNORMAL);
      SetForegroundWindow(hWnd);
      hWnd := FindWindowExA(hWnd, 0, 'EXCELC', nil);
      if (hWnd <> 0) and (IsWindowVisible(hWnd)) then begin
        for i:=1 to 9 do begin
          case i of
            3,4,5,6,9: EnableWindow(GetDlgItem(hWnd, i), False);
            else
          end;
        end;
        Break;
      end;
    end;
  end;
  Terminate;

end;
//------------------------------------------------------------------------------


Ru  2006-03-16 04:17:07  No: 20499

また書いてる最中に・・・(汗)
追記分も含めて実装指定校と思います。
ありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加