ページ 1 / 1
印刷
Posted: 2006年2月25日(土) 14:22
by M.S.
脱兎 様のトピックを見て、自分なりに考えてみましたが、
プリンタが起動するところまではいいのですが、
文字が印刷されずに紙が排出されるだけになってしまいます。
コードを載せておきますので、どこがいけないのか教えて下さい。
[ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]コード: 全て選択
Sub MainWnd_IDM_PRINT_MenuClick()
dim pd as PRINTDLG
dim docinfo as DOCINFO
dim hDC as DWord
ZeroMemory(VarPtr(pd),Len(pd))
with pd
.lStructSize=66
.hwndOwner=hMainWnd
.Flags=PD_RETURNDC
End With
if PrintDlg(pd) then
hDC=pd.hDC
ZeroMemory(VarPtr(docinfo),Len(docinfo))
docinfo.cbSize=Len(docinfo)
docinfo.lpszDocName="text"
StartDoc(hDC,docinfo)
StartPage(hDC)
EndDoc(hDC)
DeleteDC(hDC)
End If
End Sub
sub PrintData(hDC as DWord)
dim i as DWord
dim buf[225] as Byte
dim rect as RECT
' konisi 様のコードをそのまま引用===================================================================
Dim Text As String
Text=ZeroString(GetWindowTextLength(GetDlgItem(hMainWnd,EditBox1)))
GetWindowText(GetDlgItem(hMainWnd,EditBox1),Text,GetWindowTextLength(GetDlgItem(hMainWnd,EditBox1))+1)
'=============================================================================================
for i=1 to 20
wsprintf(VarPtr(buf),Text,i)
DrawText(hDC,buf,-1,rect,DT_CALCRECT)
rect.left=100
rect.right=rect.left+rect.right
rect.top=i*100
rect.bottom=rect.top+rect.bottom
DrawText(hDC,buf,-1,rect,DL_LEFT)
Next i
End Sub
全体的には、「ActiveBasicfan」の、「印刷ダイアログと印刷の仕組み」を引用しました。
Posted: 2006年2月25日(土) 16:30
by イグトランス
肝心の印刷を行うPrintData関数が呼ばれていないようです。
StartPageとEndDocの間にPrintData(hDC)を追加したらどうでしょうか。
> wsprintf(VarPtr(buf), Text, i)
ところでこれはwsprintf(buf, Text, i)でも平気ですよ。
Posted: 2006年2月26日(日) 21:42
by M.S.
イグトランス様、返信ありがとうございます。
[ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]コード: 全て選択
Sub MainWnd_IDM_PRINT_MenuClick()
dim pd as PRINTDLG
dim docinfo as DOCINFO
dim hDC as DWord
ZeroMemory(VarPtr(pd),Len(pd))
with pd
.lStructSize=66
.hwndOwner=hMainWnd
.Flags=PD_RETURNDC
End With
if PrintDlg(pd) then
hDC=pd.hDC
ZeroMemory(VarPtr(docinfo),Len(docinfo))
docinfo.cbSize=Len(docinfo)
docinfo.lpszDocName="text"
StartDoc(hDC,docinfo)
StartPage(hDC)
PrintData(hDC)
EndDoc(hDC)
DeleteDC(hDC)
End If
End Sub
IDM_PRINT のコードをイグトランス様のご指摘どおりに上記のように書き直し、
PrintData を下記のように書き直しました。
[ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]コード: 全て選択
Sub PrintData(hDC as DWord)
dim i as DWord
dim buf[225] as Byte
dim rect as RECT
Dim Text As String
Text=ZeroString(GetWindowTextLength(GetDlgItem(hMainWnd,EditBox1)))
GetWindowText(GetDlgItem(hMainWnd,EditBox1),Text,GetWindowTextLength(GetDlgItem(hMainWnd,EditBox1))+1)
for i=1 to 20
wsprintf(buf,Text,i)
DrawText(hDC,buf,-1,rect,DT_CALCRECT)
rect.left=100
rect.right=rect.left+rect.right
rect.top=i*100
rect.bottom=rect.top+rect.bottom
DrawText(hDC,buf,-1,rect,DT_LEFT)
Next i
End Sub
しかし、デバッグ中に印刷すると、アクセス違反が起きてしまいます。
(PrintData の EndSub がドラッグされた状態になります。)
一応、デバッガのメッセージを載せておきます。
コード: 全て選択
スレッド(&HBC8)はコード &H0 で終了しました。
スレッド(&H2C8)はコード &H0 で終了しました。
スレッド(&HA80)でアクセス違反がありました(EPI=&H44202020)。
何処がいけないのでしょうか?
教えて下さい、お願いします。
これで解消するか分かりませんが
Posted: 2006年3月15日(水) 10:49
by yu0627
※携帯のフルブラウザから返信しています。
これで解消するか分かりませんが、一つ怪しいところを見つけたので投稿します。
コード: 全て選択
Text=ZeroString(GetWindowTextLength(GetDlgItem(hMainWnd,EditBox1)))
GetWindowText(GetDlgItem(hMainWnd,EditBox1),Text,GetWindowTextLength(GetDlgItem(hMainWnd,EditBox1))+1)
ここが問題だと思います。上ではテキストのバイト分しかメモリを確保していませんが、下ではテキストのサイズ+1バイト分しか確保していません。だから、以下の用に修正して下さい。
コード: 全て選択
Text=ZeroString(GetWindowTextLength(GetDlgItem(hMainWnd,EditBox1))+1)
GetWindowText(GetDlgItem(hMainWnd,EditBox1),Text,GetWindowTextLength(GetDlgItem(hMainWnd,EditBox1))+1)
これでもアクセス違反が起きるならまた返信して下さい。
Re: これで解消するか分かりませんが
Posted: 2006年3月16日(木) 11:37
by M.S.
> ここが問題だと思います。上ではテキストのバイト分しかメモリを確保していませんが、下ではテキストのサイズ+1バイト分しか確保していません。だから、以下の用に修正して下さい。
コード: 全て選択
Text=ZeroString(GetWindowTextLength(GetDlgItem(hMainWnd,EditBox1))+1)
> GetWindowText(GetDlgItem(hMainWnd,EditBox1),Text,GetWindowTextLength(GetDlgItem(hMainWnd,EditBox1))+1)
これでもアクセス違反が起きるならまた返信して下さい。
コードを書き直しましたが、またアクセス違反が起きてしまいます。
スレッド(&HDF0)はコード &H0 で終了しました。
スレッド(&HDD8)はコード &H0 で終了しました。
スレッド(&HFD4)でアクセス違反がありました(EPI=&H200A0D65)。
[ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]コード: 全て選択
Sub PrintData(hDC as DWord)
dim buf[225] as Byte
dim rect as RECT
Dim Text As String
dim i as DWord
Text=ZeroString(GetWindowTextLength(GetDlgItem(hMainWnd,EditBox1))+1)
GetWindowText(GetDlgItem(hMainWnd,EditBox1),Text,GetWindowTextLength(GetDlgItem(hMainWnd,EditBox1))+1)
for i=1 to 20
wsprintf(buf,Text,i)
DrawText(hDC,buf,-1,rect,DT_CALCRECT)
rect.left=100
rect.right=rect.left+rect.right
rect.top=i*100
rect.bottom=rect.top+rect.bottom
DrawText(hDC,buf,-1,rect,DT_LEFT)
Next i
End Sub
何故でしょうか?
Re: これで解消するか分かりませんが
Posted: 2006年3月16日(木) 12:08
by yu0627
コード: 全て選択
wsprintf(buf,Text,i)
コードを見るとwsprintfの使い方が間違っていると思います。僕は印刷をしたことがないのでよくは分かりませんが、この関数の第二パラメータは変数を代入するところじゃないと思います。元々この関数は第一パラメータで指定した変数に第二パラメータで指定した書式で第三パラメータ以降の変数の内容を代入するんです。
例:
変数A:バイト型
変数B:Long型 値5
wsprintf(A, "%dページ", B)
変数Aの内容:5ページ
ですので、関数の書式を間違えたからだと思います。
Posted: 2006年9月02日(土) 15:18
by M.S.
あれから大分経って、
新しいTextEditorを作っていたときに考えたのですが、
下のコードをどなたか試していただけないでしょうか?
家のプリンタのインクが無くなって出来ないので、
どなたか宜しくお願いします。
[ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]コード: 全て選択
Sub PrintData(hDC As DWord)
Dim hEdit As HWND
Dim length As DWord
Dim buffer As BytePtr
Dim buf[255] As Byte
Dim rc As RECT
hEdit=GetDlgItem(hMainWnd,EditBox1)
length=GetWindowTextLength(hEdit)
buffer=malloc(length+1)
GetWindowText(hEdit,buffer,length+1)
wsprintf(VarPtr(buf),buffer)
DrawText(hDC,buf-1,rc,DT_CALCRECT)
rc.left=100
rc.right=rc.left+rc.right
rc.top=100
rc.bottom=rc.top+rc.bottom
DrawText(hDC,buf,-1,rc,DT_LEFT)
End Sub
Sub MainWnd_CommandButton1_Click()
Dim pd As PRINTDLG
Dim docinfo As DOCINFO
Dim hDC As DWord
Dim FileName As Byte
SendMessage(hStatus,SB_GETTEXT,0,FileName)
ZeroMemory(VarPtr(pd),Len(pd))
With pd
.lStructSize=66
.hwndOwner=hMainWnd
.Flags=PD_RETURNDC
End With
If PrintDlg(pd) Then
hDC=pd.DC
ZeroMemory(VarPtr(docinfo),Len(docinfo))
docinfo.cbSize=Len(docinfo)
docinfo.lpszDocName=FileName
StartDoc(hDC,docinfo)
StartPage(hDC)
PrintData(hDC)
EndPage(hDC)
EndDoc(hDC)
DeleteDC(hDC)
End If
End Sub
Posted: 2006年9月03日(日) 15:07
by 雷電
試してみましたが、エラーが出ますね・・・
MainWnd.sbp(724) - "DC" メンバは定義されていません
MainWnd.sbp(724) - "pd.DC" 無効な識別子です
MainWnd.sbp(151) - "DrawText" のパラメータ指定が間違っています
MainWnd.sbp(151) - "DT_CALCRECT" 無効な識別子です
MainWnd.sbp(151) - "rc" 型が違います
PrintDataの方はグローバルに書きましたが、無理ですね・・・
何か定義が抜けているようです・・・
Posted: 2006年9月26日(火) 18:29
by M.S.
返信遅くなってしまってすいません。
この前の投稿は、PC の画面を見ながら写して、
携帯からものなので、どこかが抜けていたのだと思います。
では、改めて投稿したいと思います。
[ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]コード: 全て選択
Sub MainWnd_IDM_PRINT_MenuClick()
dim pd as PRINTDLG
dim docinfo as DOCINFO
dim hDC as HDC
dim FileName as Byte
SendMessage(hStatus,SB_GETTEXT,0,FileName)
ZeroMemory(VarPtr(pd),Len(pd))
with pd
.lStructSize=66
.hwndOwner=hMainWnd
.Flags=PD_RETURNDC
End With
if PrintDlg(pd) then
hDC=pd.hDC
ZeroMemory(VarPtr(docinfo),Len(docinfo))
docinfo.cbSize=Len(docinfo)
docinfo.lpszDocName=FileName
StartDoc(hDC,docinfo)
StartPage(hDC)
PrintData(hDC)
EndPage(hDC)
EndDoc(hDC)
DeleteDC(hDC)
End If
End Sub
sub PrintData(hDC as HDC)
dim hEdit as HWND
Dim length As DWord
Dim buffer As BytePtr
dim buf[255] as Byte
dim rc as RECT
hEdit=GetDlgItem(hMainWnd, EditBox1)
length=GetWindowTextLength(hEdit)
buffer=malloc(length+1)
GetWindowText(hEdit, buffer, length+1)
wsprintf(VarPtr(buf),buffer)
DrawText(hDC,buf,-1,rc,DT_CALCRECT)
rc.left=100
rc.right=rc.left+rc.right
rc.top=100
rc.bottom=rc.top+rc.bottom
DrawText(hDC,buf,-1,rc,DT_LEFT)
End Sub
よろしくお願いします。
Posted: 2006年9月26日(火) 22:56
by 雷電
印刷ボタンを押したときにデバッガーが止まったので、何で止まるんだろう・・・?と思いながらProjectEditorを見たら、アクセス違反で止まってました・・・。
コード: 全て選択
StartDoc(hDC,docinfo)
この部分で、デバッガーがアクセス違反だとしています。
コンパイル時のエラーはなくなりましたが、デバッグしたときにまだエラーが出ますね・・・
今度は「猫でもわかるプログラミング」を参考にしました
Posted: 2007年6月07日(木) 22:25
by M.S.
関数 [ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]コード: 全て選択
Declare Function SetAbortProc lib "gdi32" (hdc As HDC,lpAbortProc As DWord) As Long
Declare Function AbortDoc lib "gdi32" (hDC As HDC) As Long
Declare Function OpenPrinter lib "winspool" alias "OpenPrinterA" (pPrinterName As *Char,phPrinter As VoidPtr,ByRef pDefault As PRINTER_DEFAULTS) As Long
Declare Function ClosePrinter lib "winspool" (hPrinter As HANDLE) As Long
Declare Function PrinterProperties lib "winspool" (hWnd As HWND,hPrinter As HANDLE) As Long
Type PRINTER_DEFAULTS
pDatatype As String
pDevMode As Long
pDesiredAccess As Long
End Type
' 印刷関数
Function MyPrint() As Long
Dim hdc As HDC
Dim docinfo As DOCINFO
ZeroMemory(VarPtr(docinfo),Len(docinfo))
docinfo.cbSize = sizeof(DOCINFO)
docinfo.lpszDocName = "testprint"
hdc = GetPrintInfo()
hCancelDlgWnd = CreateDialog(hMainWnd, "PRNSTOP")
ShowWindow(hCancelDlgWnd, SW_SHOW)
EnableWindow(hMainWnd, FALSE)
SetAbortProc(hdc, AddressOf(MyAbortProc))
Dim length As DWord
Dim buffer As BytePtr
'テキスト データを格納するためのバッファ領域を確保
length=GetWindowTextLength(hEdit)
buffer=malloc(length+1)
'テキスト バッファを取得
GetWindowText(hEdit, buffer, length+1)
StartDoc(hdc, docinfo)
StartPage(hdc)
TextOut(hdc, 20, 20, buffer, length)
If bCancel Then
AbortDoc(hdc)
else
DestroyWindow(hCancelDlgWnd)
End If
EndPage(hdc)
EndDoc(hdc)
EnableWindow(hMainWnd, TRUE)
SetFocus(hMainWnd)
DeleteDC(hdc)
MyPrint=0
'バッファを解放する
free(buffer)
End Function
' プリンタ情報を取得する
Function GetPrintInfo() As HDC
Dim dwNeeded As DWORD, dwReturned As DWORD
If EnumPrinters(PRINTER_ENUM_DEFAULT, NULL, 5, VarPtr(prninfo), Len(prninfo), dwNeeded, dwReturned) Then
GetPrintInfo=CreateDC(NULL, prninfo[0].pPrinterName, NULL,ByVal 0)
Else
GetPrintInfo=0
End If
End Function
Function MyAbortProc(hDC As HDC,int As Long)
Dim msg As MSG
While PeekMessage(msg, NULL, 0, 0, PM_REMOVE)
If IsDialogMessage(hCancelDlgWnd, msg) Then
TranslateMessage(msg)
DispatchMessage(msg)
End If
Wend
MyAbortProc=bCancel
End Function
' 印刷中止
Function MyPrnCancelProc(hWnd As HWND,msg As DWord,wp As WPARAM,lp As LPARAM) As LRESULT
Select Case msg
Case WM_INITDIALOG
SetFocus(hWnd)
MyPrnCancelProc=TRUE
Case WM_COMMAND
If LOWORD(wp) = IDCANCEL Then
bCancel = TRUE
DestroyWindow(hCancelDlgWnd)
MyPrnCancelProc=TRUE
End If
End Select
MyPrnCancelProc=FALSE
End Function
Function PrinterSet() As Long
Dim hPrint As HANDLE
GetPrintInfo()
OpenPrinter(prninfo[0].pPrinterName, hPrint,ByVal 0)
PrinterProperties(hParent, hPrint)
ClosePrinter(hPrint)
PrinterSet=0
End Function
[ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]コード: 全て選択
Dim hEdit As HWND
Dim hParent As HWND, hCancelDlgWnd As HWND
Dim hInst As HINSTANCE
Dim bCancel = FALSE As Long
Dim prninfo[3] As PRINTER_INFO_5
Sub MainWnd_Create(ByRef CreateStruct As CREATESTRUCT)
hEdit=GetDlgItem(hMainWnd,EditBox1)
End Sub
' 印刷
Sub MainWnd_CommandButton1_Click()
PrinterSet()
GetPrintInfo()
MyPrint()
End Sub
これで印刷をやってみたら、
リリースコンパイルのほうは何の反応もなく、
デバッグ実行のときだけ印刷されましたが、
印刷される文字は改行もされず、
紙の右端まで行くと文の途中にも関わらず印刷が終わってしまいます。
自分ではこれが精一杯ですので、
どなたか力を貸してください。
お願いします。
AB: 4.24.00
参考ページ:
猫でもわかるプログラミング 第78章、
同 第79章
Re: 今度は「猫でもわかるプログラミング」を参考にしました
Posted: 2007年6月08日(金) 07:31
by tak
> 印刷される文字は改行もされず、
> 紙の右端まで行くと文の途中にも関わらず印刷が終わってしまいます。
印刷可能領域をはみ出しているのではないでしょうか。
TextOut() が使われていますが、同様の方法でプリンタではなくウィンドウにテキストを描画しても、はみ出した部分は表示されませんよね。
自分で改行付加の処理を追加しないと表示されないはずです。
これがまた面倒なのですが、WinAPI に便利なオプションとかないんですかね?
> リリースコンパイルのほうは何の反応もなく、
> デバッグ実行のときだけ印刷されましたが、
こっちの問題はわかりません。
これに限らず、リリース版とデバッグ版とで挙動が異なる場合があるようですが、自分はそういう現象に遭遇したことはないです。
あとで空いた時間にこのプログラムを実行して確かめてみようと思います。
Re: 今度は「猫でもわかるプログラミング」を参考にしました
Posted: 2007年6月08日(金) 11:26
by NoWest
> > 印刷される文字は改行もされず、
> > 紙の右端まで行くと文の途中にも関わらず印刷が終わってしまいます。
>
> 印刷可能領域をはみ出しているのではないでしょうか。
> TextOut() が使われていますが、同様の方法でプリンタではなくウィンドウにテキストを描画しても、はみ出した部分は表示されませんよね。
> 自分で改行付加の処理を追加しないと表示されないはずです。
> これがまた面倒なのですが、WinAPI に便利なオプションとかないんですかね?
DrawText関数は改行にも対応してませんでしたっけ?
Re: 今度は「猫でもわかるプログラミング」を参考にしました
Posted: 2007年6月08日(金) 18:25
by M.S.
> DrawText関数は改行にも対応してませんでしたっけ?
コード: 全て選択
StartDoc(hdc, docinfo)
StartPage(hdc)
TextOut(hdc, 20, 20, buffer, length)
の部分を、
コード: 全て選択
StartDoc(hdc, docinfo)
StartPage(hdc)
Dim rc As RECT
DrawText(hdc,buffer,length,rc,DT_CALCRECT)
rc.left=20
rc.top=20
rc.right=rc.left+rc.right
rc.bottom=rc.top+rc.bottom
DrawText(hdc,buffer,length,rc,DT_LEFT)
に変更してみると、テキストの改行がうまくいきました。
NoWest さん、ありがとうございます。
しかし、はみ出した部分の改行ができません、
どうすれば良いのでしょうか?