こんにちは。データを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;
Excel PrintPreviewの表示は別スレッドで実行するべきでしょう。
Previewウィンドウが表示された時点でボタンを無効化すればOK。
返信ありがとうございます。
あれから調べていまして,スレッドならもしかしてできるのかなと思い,
ソース組んでいました。もう少し頑張ってみます。ありがとございます。
スレッド初挑戦・・・
ボタンの無効化を別スレッドにした方が楽か…
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;
スレッドの使用で少し手こずっているのですが,
以下のソースで実行しデバックで追ったところ,
スレッド側の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;
//=======================================================
あ、書いてる間に更新されてたのですね・・・
申し訳ありません。
だいあんさん、別案さんありがとうございます。m(_ _)m
再度試してきます。
おはようございます。
だいあんさんの手法でプレビュー時の任意のボタンの無効化には成功しました。
ただ,プレビューまでに若干時間かかる為,メインExcelが確認ぐらい見えてしまいますので,
現在瞬間的にプレビュー画面が出るようにする、もしくはExcelの表示はせずに
Excelプレビューを出す方法を考えています。
質問ばかりで恐縮なのですが,また相談乗ってもらえると嬉しいです。
どなたかご存じの方がいれば教えていただけると幸いです。よろしくお願いし増す。
============================================================
今気になって考えいるところ
============================================================
プレビューする時はプレビュー指令より先に,
Excel.Visible := True
はどうしてもいるのでしょうか?
delphi-MLの方に似たようなソースはあったのですが,
プレビュー指令後,画面に表示されずにプログラムが止まりました。
おそらくプレビュー中で固まっているのだとは思うんですが。
あとプレビュー中はSetTimerは効かないのでしょうか?
それとも使用方法が悪いのでしょうか・・・
ワークシートも印刷プレビューも同じハンドル値のEXCELウィンドウに表示されているのだから、表示させなければ無理。
Excel.Visible := False;
にしておいて、別スレッドの中で
.....
hW := FindWindowExA(0, 0, 'XLMAIN', nil);
if hW <> 0 then begin
ShowWindow(hW, SW_SHOWNORMAL);
SetForegroundWindow(hW);
end;
.....
と、表示させれば多少はマシ?気休め程度?
ちょっとダケヨ
> .....
> hW := FindWindowExA(0, 0, 'XLMAIN', nil);
Sleep(500);
> if hW <> 0 then begin
> ShowWindow(hW, SW_SHOWNORMAL);
> SetForegroundWindow(hW);
> end;
> .....
きやすめさん。返信ありがとうございます。
教えていただいたソースで試したところ,かなり早くなりました。
若干見えるのは,使用に影響及ぼさない時間なのでこのまま様子見ようと思います。
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;
//------------------------------------------------------------------------------
また書いてる最中に・・・(汗)
追記分も含めて実装指定校と思います。
ありがとうございました。
ツイート | ![]() |