PDA

View Full Version : سوال: يونيت printers



m.amiri
شنبه 04 تیر 1390, 13:20 عصر
سلام دوستان
من ميخوام با استفاده از يونيت پرينتر و دستور
('اين تست است',printer.canvas.textout(x,y
جمله ي "اين تست است" رو تو مختصات x,y چاپ كنم كه اين كارو مي كنه
ولي فاصله ي x رو از آخر جمله يعني كلمه ي "است" حساب ميكنه ،ما چون
از راست به چپ مينويسيم مي خوام اين فاصله رو از اول جمله يعني
كلمه ي "اين" حساب كنه اين دستور تو كتاب قمي بود
خواهشا اگه كسي ميدونه كمكم كنه سپاسگزارم

SAASTN
شنبه 04 تیر 1390, 19:27 عصر
این قضیه به یونیت Printers ربطی نداره، کلا TCanvas بطور پیشفرض از چپ به راست می نویسه. اینو یه تست کن:
procedure DrawRtLText(Canvas: TCanvas; X, Y: Integer; Text: string);
var
aRect: TRect;
begin
aRect := Rect(0, 0, 0, 0);
Canvas.TextRect(aRect, Text, [tfCalcRect]);
aRect.Left := X - aRect.Right;
aRect.Right := X;
aRect.Top := Y;
aRect.Bottom := Y + aRect.Bottom;
Canvas.TextRect(aRect, Text);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
DrawRtLText(Canvas, 100, 100, 'این یک تست است');
Canvas.Pixels[100, 100] := clRed; // for test
end;

m.amiri
دوشنبه 06 تیر 1390, 20:14 عصر
سلام آقاي مهندس
من از قطعه كد شما چيزي نفهميدم تو كامپيوتر هم خطاي دستوري داره
ولي مشكل من در رابطه با پرينت گرفتنه من ميخوام يه جمله اي رو پرينت كنم
و ميخوام از اول جمله تراز بشه (جمله فارسي) يعني وقتي جمله" اين تست است" رو
گفتم در مكان 100و100 چاپ كنه از اين مكان شروع به چاپ و به سمت چپ گسترشش بده
دستوري رو هم كه نوشتم گفتم عينا از كتاب قمي بود ولي الزامي ندارم حتما از اين دستور استفاده
كنم ممنون ميشم اگه كسي در اين زمينه چيزي ميدونه بگه خدا عوضتون بده.

SAASTN
دوشنبه 06 تیر 1390, 20:34 عصر
یعني وقتي جمله" اين تست است" رو گفتم در مكان 100و100 چاپ كنه از اين مكان شروع به چاپ و به سمت چپ گسترشش بده
کدی که قرار دادم همین کار رو بدون مشکل انجام میده.
یه کلید روی فرمتون قرار بدید و خطهای 16 و 17 رو در OnClickش بنویسید.
روال DrawRtLText رو هم عینا در همون یونیت کپی کنید.
حالا بگید با چه خطایی روبرو شدید.
------------------------
اما توضیح در مورد کد: کلا از کلاس TCanvas برای ترسیمات در دلفی استفاده میشه. متد TextRect متن رو در یک کادر مشخص تعیین می کنه، بر خلاف TextOut که تنها یک نقطه برای ترسیم میگیره. در خط 6ام کد بالا متد TextOut با پارامتر tfCalcRect فراخونی شده که باعث ترسیم واقعی متن نمی شه، بلکه ابعاد متن بعد از ترسیم رو محاسبه می کنه و در متغیر aRect قرار میده. حالا ما عرض و ارتفاع متن رو در اختیار داریم، ابعاد aRect رو به نحوی تغییر میدیم که سمت راست متن بعد از ترسیم در موقعیت X و Y قرار بگیره و در خط 11 متن ترسیم میشه.

اگر موفق شدید که متن رو روی فرمتون در موقعیت دلخواه ببینید و مشکل حل شد، برای کار با پرینتر DrawRtLText به اینصورت فراخونی کنید:
DrawRtLText(Printer.Canvas, 100, 100, 'این یک تست است');

m.amiri
دوشنبه 06 تیر 1390, 21:03 عصر
سه تا خطا ميده دو تا مال خط ششه و يكيش خط يازده
6 incompatibel type integer , string
6 incompatibel type integer,set
11 incompatibel type integer , string

SAASTN
دوشنبه 06 تیر 1390, 21:38 عصر
به نظر میاد تنها یک Overload از متد TextRect در سیستم شما معتبره. از چه نسخه ای از دلفی استفاده می کنید؟
و لطفا چک کنید که متد Canvas.TextExtent هم خطا داره یا نه.

m.amiri
سه شنبه 07 تیر 1390, 12:02 عصر
سلام
از دلفي 7 استفاده ميكنم و تابع Canvas.TextExtent رو هم با يه پارامتر از نوع string دارم
اين دستور Canvas.TextRect كه خطا داره 4 تا پارامتر ميگيره پاراlتر اولش از نوع trect ودومي و سومي integer و چهارمي از نوع string هستش البته تو دلفيه من
كه شما تو خط 6 ،4 تا پارامتر بهش دادين اوليش trect دوميش string و سوميش هم نميدونم چيه
و تو خط 11 به همين تابع 2 تا پارامتر دادين اوليش trect و دوميش string

m.amiri
سه شنبه 07 تیر 1390, 12:14 عصر
شرمنده اينو نوشتم تا يكي به پاسخ ها اضافه كنه تا شما متوجه پيام من بشيد

SAASTN
سه شنبه 07 تیر 1390, 13:33 عصر
اين دستور Canvas.TextRect كه خطا داره 4 تا پارامتر ميگيره پاراlتر اولش از نوع trect ودومي و سومي integer و چهارمي از نوع string هستش البته تو دلفيه من
كه شما تو خط 6 ،4 تا پارامتر بهش دادين اوليش trect دوميش string و سوميش هم نميدونم چيه
و تو خط 11 به همين تابع 2 تا پارامتر دادين اوليش trect و دوميش string
بله درسته، اما توی دلفی XE دوتا overload از TextRect وجود داره. یکی به همون ترتیبی که گفتید و یکی به ترتیبی که من استفاده کردم. منم حافظه ام فسیل شده، تا جایی که یادم میاد تو دلفی 7هم با همین TextRect کار می کردیم.:متفکر:
ولی به هر صورت روال DrawRtLText رو بصورت زیر تغییر بدید، انشا ا... که دیگه مشکلی پیش نیاد:
procedure DrawRtLText(Canvas: TCanvas; X, Y: Integer; Text: string);
var
aRect: TRect;
TextSize: TSize;
begin
TextSize := Canvas.TextExtent(Text);
aRect.Left := X - TextSize.cx;
aRect.Right := X;
aRect.Top := Y;
aRect.Bottom := Y + TextSize.cy;
Canvas.TextRect(aRect, Text);
end;

و البته شما که تازه چند وقته دلفی رو شروع کردی (بنا به گفته خودتون تو تاپیک چرا دلفی؟)، چرا با دلفی 7؟!

m.amiri
چهارشنبه 08 تیر 1390, 11:59 صبح
سلام دوست من
اين كد آخريه جواب داد البته باكمي تغيير ;( Canvas.TextRect(aRect,arect.Left,arect.Top, Text
بجاي ;(Canvas.TextRect(aRect, Text
ولي به هر حال خيلي كمك كردين
اما اين روي فرم چاپ مي كنه اون دستور printer.canvas هم كه نوشته بودين
خطا موقع كمپايل ندارن اما موقع اجرا داره ميگه printer is not curetly printing
بعد يه سوال هم داشتم در مورد فونت و سايز چاپ بايد چكار كنم
يه دنيا ممنونتونم

SAASTN
چهارشنبه 08 تیر 1390, 23:33 عصر
اين كد آخريه جواب داد البته باكمي تغيير ;( Canvas.TextRect(aRect,arect.Left,arect.Top, Text
بجاي ;(Canvas.TextRect(aRect, Text
آقا شرمنده، بازم خنگ بازی درآوردم و TextRect دوم رو اصلاح نکردم.

اما اين روي فرم چاپ مي كنه اون دستور printer.canvas هم كه نوشته بودين
خطا موقع كمپايل ندارن اما موقع اجرا داره ميگه printer is not curetly printing
خوب قبل از ترسیم باید پرینتر رو Start کنید. این یه نمونه برای پرینت گرفتن با Canvasه:
// A subroutine used to display a print-cancel dialog
procedure CancelDialog;
begin
// Display the cancel print dialog
Dialogs.MessageDlg('Press cancel to abort printing',mtCustom,[mbCancel],0);

// Now that the user has pressed cancel, we abort the printing
if Printer.Printing then
begin
Printer.Abort;
ShowMessage('Printing aborted');
end;

// End this thread
endThread(0);
end;

// The main form On Create routine - our main program
procedure TForm1.FormCreate(Sender: TObject);
const
TOTAL_PAGES = 4; // How many pages to print
var
printDialog : TPrintDialog;
cancelThreadId : Integer;
threadId : LongWord;
page, startPage, endPage : Integer;

begin
// Create a printer selection dialog
printDialog := TPrintDialog.Create(Form1);

// Set up print dialog options
printDialog.MinPage := 1; // First allowed page number
printDialog.MaxPage := TOTAL_PAGES; // Highest allowed page number
printDialog.ToPage := TOTAL_PAGES; // 1 to ToPage page range allowed
printDialog.Options := [poPageNums]; // Allow page range selection

// if the user has selected a printer (or default), then print!
if printDialog.Execute then
begin
// Start a cancel print dilaog as a separate thread!
// cancelThreadId := beginThread(nil,
// 0,
// Addr(CancelDialog),
// nil,
// 0,
// threadId);

// Use the Printer function to get access to the global TPrinter object.
// Set to landscape orientation
Printer.Orientation := poLandscape;

// Set the printjob title - as it it appears in the print job manager
Printer.Title := 'Test print for Delphi';

// Set the number of copies to print each page
// This is crude - it doies not take Collation into account
Printer.Copies := printDialog.Copies;

// Start printing
Printer.BeginDoc;

// Has the user selected a page range?
if printDialog.PrintRange = prPageNums then
begin
startPage := printDialog.FromPage;
endPage := printDialog.ToPage;
end
else // All pages
begin
startPage := 1;
endPage := TOTAL_PAGES;
end;

// Set up the start page number
page := startPage;

// Keep printing whilst all OK
while (not Printer.Aborted) and Printer.Printing do
begin
// Show a message saying we are starting a page
if MessageDlg('Starting to print page '+IntToStr(page), mtConfirmation,
[mbOK, mbCancel], 0) = mrCancel
then
Break;

// Set up a medium sized font
Printer.Canvas.Font.Size := 10;

// Allow Windows to keep processing messages
Application.ProcessMessages;

// Write out the page number
Printer.Canvas.Font.Color := clBlue;
Printer.Canvas.TextOut(40, 20, 'Page number = '+IntToStr(page));

// Underline this page number
Printer.Canvas.MoveTo(40,80);
Printer.Canvas.LineTo(Printer.PageWidth-20,80);

// Write out the page size
Printer.Canvas.Font.Color := clRed;
Printer.Canvas.TextOut(40, 100, 'Page width = '+
IntToStr(Printer.PageWidth));
Printer.Canvas.TextOut(40, 180, 'Page height = '+
IntToStr(Printer.PageHeight));

// Increment the page number
Inc(page);

// Now start a new page - if not the last
if (page <= endPage) and (not Printer.Aborted)
then Printer.NewPage;
end;

// Finish printing
Printer.EndDoc;
end;
end;

من بدون مشکل پرینت گرفتم. برای اینکه ببینید تو هر بخش چه اتفاقی داره میوفته توی مرجعش توضیحات کاملی وجود داره:
http://www.delphibasics.co.uk/Article.asp?Name=Printing
البته من یه تغییر کوچیک تو کد آخر دادم و اونم حذف cancelThreadId و اون MessageDlg هست. چون کد اینجوریه که قبل از شروع به چاپ هر صفحه میپرسه و تو کد اصلی ادامه می داد تا تو اون یکی پنجره Abort کنید و بعد از Abort هم یه خطا میداد و کار درست انجام نمی شد.

بعد يه سوال هم داشتم در مورد فونت و سايز چاپ بايد چكار كنم
برای تغییر مشخصات قلم از Canvas.Font استفاده کنید. ابعاد ترسیم هم که توی همون کد بالا مشخص شده.
اما دقیقا چکار می خواید بکنید؟ اگه منظورتون ایجاد یه گزارشه این مسیر اصلا مسیر درستی نیست. بهتره برید سراغ ابزارای گزارش سازی. QuickReport گزینه خوبیه و خیلی سریع توش راه میافتید و به نتیجه میرسید. باهاش هم میتونید گزارشای استاتیک درست کنید و هم راحت به دیتابیس متصل میشه. نمونه و راهنما هم زیاد براش گیر میاد. و البته گزینه های دیگه ای هم هست و برای گزارشای پیچیده باید برید سراغ ابزارای کامل تر.

m.amiri
جمعه 10 تیر 1390, 16:34 عصر
سلام
من ميخوام يه نرم افزار براي تايپ مشخصات روي چك بنويسم
البته يه بار با فست ريپورت نوشتمش اما كار كردن با اون يه كم براي كاربرا سخته
مي خوام بدونه استفاده از نرم افزار هاي گزارش گيري دوباره بنويسمش فكر ميكنم
اين بهتر بشه حالا هنوز كد شما رو نديدم برم ببينم سر در ميارم يا نه!

m.amiri
جمعه 10 تیر 1390, 17:48 عصر
سلام مهندس جان
من كه از اين قطعه كد بالا زياد سر در نياوردم البته
به اون لينك هم رفتم ظاهرا از همونجا كپي كرده بوديد
اما مشكلم حل شد همون يك كلمه enddok رو كه ديدم تا آخرشو رفتم
در مورد مشخصات فونت هم مشكلم حل شد اما نميدونم چطور پيكسلو به سانتي متر تبديل كنم
تو پرينتر من هر 250 پيكسل يك سانتي متره ولي فكر ميكنم تو پرينتر هاي
ديگه فرق كنه راستي پروژه مو كه گفتم چيه اگه شما پيشنهادي برام دارين
برام بنويسيد اون پروژه قبلي كه گفتم با فست ريپورت نوشتم هم آماده شده
اگه ميخوايند ميلتونو بدين واستون بفرستم

SAASTN
یک شنبه 12 تیر 1390, 11:41 صبح
سلام، ببخشید که کمی دیر شد ...

من ميخوام يه نرم افزار براي تايپ مشخصات روي چك بنويسم
حالا این برنامه برنامه ریپورتای بزرگ و پیچیده ای نداره و می تونید برای تجربه هم که شده با Canvas کارکنید. ولی بازم تصور می کنم استفاده از ابزارای گزارش سازی مسیر درست تریه.

البته يه بار با فست ريپورت نوشتمش اما كار كردن با اون يه كم براي كاربرا سخته
مگه قراره کاربر باهاش چکار کنه؟ شما یه Preview نمایش میدی اونم رو دکمه پرینت کلیک می کنه دیگه.

به اون لينك هم رفتم ظاهرا از همونجا كپي كرده بوديد
ظاهرا!!:لبخند:

در مورد مشخصات فونت هم مشكلم حل شد اما نميدونم چطور پيكسلو به سانتي متر تبديل كنم
تو پرينتر من هر 250 پيكسل يك سانتي متره ولي فكر ميكنم تو پرينتر هاي
ديگه فرق كنه
توی این لینک یه مثال دیگه هست که این مسائل رو هم در نظر گرفته:
http://www.swissdelphicenter.ch/torry/showcode.php?id=1783
اما بخشی که برای بدست آوردن رزولوشن هست اینه:
{ Get resolution, paper size and non-printable margin from
printer driver. }
procedure GetPrinterParameters(out X_resolution, Y_resolution: Integer;
out pagerect : TRect; out printorigin : TPoint);
begin
{ X_resolution : horizontal printer resolution, in dpi }
{ Y_resolution : vertical printer resolution, in dpi }
{ pagerect : total page, in paper coordinates }
{ printorigin : origin of canvas coordinate system in paper coordinates. }
with Printer.Canvas do
begin
X_resolution := GetDeviceCaps(Handle, LOGPIXELSX);
Y_resolution := GetDeviceCaps(Handle, LOGPIXELSY);
printorigin.X := GetDeviceCaps(Handle, PHYSICALOFFSETX);
printorigin.Y := GetDeviceCaps(Handle, PHYSICALOFFSETY);
pagerect.Left := 0;
pagerect.Right := GetDeviceCaps(Handle, PHYSICALWIDTH);
pagerect.Top := 0;
pagerect.Bottom := GetDeviceCaps(Handle, PHYSICALHEIGHT);
end; { With }
end; { GetPrinterParameters }

فقط توجه داشته باشید که رزولوشن در واحد dpi برمی گرده و خودتون باید اینچ رو به سانتی متر تبدیل کنید.

راستي پروژه مو كه گفتم چيه اگه شما پيشنهادي برام دارين برام بنويسيد
چیزی که به ذهنم میرسه اینه که تا جایی که می تونید برنامتون رو پارامتریک بنویسید و پارامتر ها رو توی یک پنجره تنظیمات در اختیار کاربر قرار بدید. یه چیزایی مثل ابعاد، مقیاس ها و جابجایی ها و ... تا اگه مسائل پیشبینی نشده ای روی سیستم های مختلف اتفاق افتاد برنامه بی کاربرد نشه.

m.amiri
سه شنبه 14 تیر 1390, 08:01 صبح
سلام مهندس
چند روزي سرم شلوغ بود نتونسم زياد سر بزنم
ببخشيد ديگه
ببينيد مشخصات چكها متفاوته مثلا مبلغ چك تو چكها پايين چپ يا پيين راست يا بالا چپ هستش
اينه كه كاربر بايد به صفحه طراح گزارش دسترسي داشته باشه كه تو فست ريپورت اين قابليت هست
اما اين كار براي كاربراي امروزي سخته
در مورد لينك و كدي كه معرفي كردين مطلبو گرفتم ولي من نميدونم چطوري با دونستن dpi يا pixelperinch تو كامپيوتر كاربر
براي هر سانت چند پيكسل بايد جلو بيام طريقه استفاده شو نميدونم
از توجه تونه ممنونم

SAASTN
سه شنبه 14 تیر 1390, 12:17 عصر
ببينيد مشخصات چكها متفاوته مثلا مبلغ چك تو چكها پايين چپ يا پيين راست يا بالا چپ هستش
اينه كه كاربر بايد به صفحه طراح گزارش دسترسي داشته باشه كه تو فست ريپورت اين قابليت هست
اما اين كار براي كاربراي امروزي سخته
ای بابا! دیگه حداقل کاری که یه برنامه پرینت چک باید انجام بده اینه که 10-20 تا template برای چکای مختلف داشته باشه. این چیزی که شما می گی برای کاربرای تمام دورانها سخت بوده، کاربر باید از یه Combo نوع دسته چکش رو انتخاب کنه و تمام.
بعدشم، حالا این کار سخت رو با Canvas چطور می خواین ساده کنید؟!

در مورد لينك و كدي كه معرفي كردين مطلبو گرفتم ولي من نميدونم چطوري با دونستن dpi يا pixelperinch تو كامپيوتر كاربر براي هر سانت چند پيكسل بايد جلو بيام طريقه استفاده شو نميدونم
کد زیر یه خط به طول 5 سانت و ضخامت یک میل میکشه، پرینت گرفتم و با خطکش اندازه گرفتم.

uses
StdConvs;
...
var
X_resolution_dpi, Y_resolution_dpi: Integer;
X_resolution_dpcm, Y_resolution_dpcm: Double;
...
with Printer.Canvas do
begin
X_resolution_dpi := GetDeviceCaps(Handle, LOGPIXELSX);
Y_resolution_dpi := GetDeviceCaps(Handle, LOGPIXELSY);
end;
X_resolution_dpcm := X_resolution_dpi / (MetersPerInch * 100);
Y_resolution_dpcm := Y_resolution_dpi / (MetersPerInch * 100);
Printer.Canvas.Pen.Width := Round(0.1 * X_resolution_dpcm);
Printer.Canvas.MoveTo(Round(4 * X_resolution_dpcm), Round(4 * Y_resolution_dpcm));
Printer.Canvas.LineTo(Round(7 * X_resolution_dpcm), Round(8 * Y_resolution_dpcm));

m.amiri
پنج شنبه 16 تیر 1390, 11:09 صبح
سلام
ما كه مشخصات تمام چكهاي موجود تو جامعه رو مداريم
مخصوصا موسسه هاي اعتباري ها و قرض الحسنه ها كه مثل قارچ دارن زياد ميشن
و بعضا طرح چكاشون رو هم عوض ميكنن پس ما بايد يه قابليت طراحي تو برنامه مون داشته باشيم
برنامه هاي موجود تو بازارو هم كه الان دارن تو اينترنت فروخته ميشن من ديدم همين طورن
اما چون كار با صفحه طراح فست ريپورت براي كاربرا سخته من ميخوام مشخصات چك مثل
ابعاد چك و موقعيت هر فيلد در چك از چپ و بالا رو يه بار از كاربر گرفته و بجاي ذخيره در فايل فست ريپورت
تو يه ديتابيس ذخيره كنم و همون طور كه شما گفتيد با يه كمبو كاربر انتخاب و طبق فاصله هايي كه كاربر از
چپ و بالا داده بوسيله كانواز چاپ كنم برنا مه هاي تو بازار هم دقيقا مثل اين طرح دومند كه گفتم

بوسيله

m.amiri
پنج شنبه 16 تیر 1390, 12:43 عصر
سلام
درباره اين كدي كه نوشتين كه خط 5 سانتي چاپ ميكنه دستور GetDeviceCaps
رو نگه همينطر استفاده كنم صفر برميگردونه و اگه زيره with Printer.Canvas do
استفاده كنم خطا موقع اجرا داره و در مورد MetersPerInch هم بايد بگم كه
همچين پارامتري نداره البته دلفي 7
ولي كدتون رو كاملا متوجه شدم اگه بتونم X_resolution_dpcm و y_resolution_dpcm رو
از سيستم كاربر بگيرم فكر كنم مشكلم حل ميشه

SAASTN
پنج شنبه 16 تیر 1390, 14:24 عصر
ما كه مشخصات تمام چكهاي موجود تو جامعه رو مداريم
منم نگفتم همه، 10-20 از چکای رایج رو که میشه گیر آورد که درصد بالایی از کاربرا رو پوشش میده. مگه چقدر از بازاریا و کاسبا از این موسسات قارچی دسته چک می گیرن؟ حالا امکان طراحی یه قابلیت ویژه ست برای دسته چک های خاص تر. منم برنامه ای که دیدم همین طور رفتار می کرد، یعنی وقتی یا رو می خواست حسابشو به برنامه معرفی کنه توی یه کمبو انواع دسته چک ها لیست شده بود، حالا من دیگه نمی دونم دیزاینر هم داشت یا نه.
ببینید آخه برگه چک که یه تیکه کاغذ الکی نیست بشه باهاش هی تست گرفت و چک و انداخت دور. شما خودت بخوای یه ریپورت درست کنی باید حداقل 5-6 تا تست بگیری، حالا دیگه حساب کاربر رو بکن.

درباره اين كدي كه نوشتين كه خط 5 سانتي چاپ ميكنه دستور GetDeviceCaps رو نگه همينطر استفاده كنم صفر برميگردونه
اگر اون with رو نذارید Handle به هندل خود فرم اشاره می کنه وجواب هرچی که باشه نا معتبره.

اگه زيره with Printer.Canvas do استفاده كنم خطا موقع اجرا داره
نمی دونم، من حتی موقعی که پرینترم خاموشه خطا ندارم. مثل اینکه این اطلاعات رو کلا از Driver می خونه. متن خطا چیه؟

در مورد MetersPerInch هم بايد بگم كه همچين پارامتري نداره البته دلفي 7
StdConvs رو use کردین؟ ولی به هر صورت اینه:
const
MetersPerInch = 0.0254; // [1]

m.amiri
جمعه 17 تیر 1390, 17:54 عصر
نمی دونم، من حتی موقعی که پرینترم خاموشه خطا ندارم. مثل اینکه این اطلاعات رو کلا از Driver می خونه. متن خطا چیه؟

سلام stdcanvas رو use كردم
متن خطا هم printe is not currently printing هستش

m.amiri
جمعه 17 تیر 1390, 18:14 عصر
سلام مهندس
درست شد begendoc و enddoc رو تو كدتون ننوشته بودين
وقتي نوشتم درست شد