Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 11/12/19 in Posts

  1. David Heffernan

    How to manage defined list values

    I use attributes attached to enumerated types to handle this
  2. The Windows imaging Component contains a wealth of useful features for manipulating images in different formats. Delphi partially encapsulates this functionality into the TWICImage class of Vcl.Graphics which is a TGraphics descendent. The following code resizes pf32bit bitmaps with transparency using TWICImage, at a much better quality than can be achieved with StretchDraw for example or anything else I have tried.. Uses Winapi.Wincodec, Vcl.Graphics; procedure ResizeBitmap(Bitmap: TBitmap; const NewWidth, NewHeight: integer); var Factory: IWICImagingFactory; Scaler: IWICBitmapScaler; Source : TWICImage; begin Bitmap.AlphaFormat := afDefined; Source := TWICImage.Create; try Factory := TWICImage.ImagingFactory; Source.Assign(Bitmap); Factory.CreateBitmapScaler(Scaler); Scaler.Initialize(Source.Handle, NewWidth, NewHeight, WICBitmapInterpolationModeHighQualityCubic); Source.Handle := IWICBitmap(Scaler); Bitmap.Assign(Source); Scaler := nil; Factory := nil; finally Source.Free; end; end; Some key points: Setting the AlphaFormat to alDefined is crucial for maintaining the transparency. If you do not release the ImageFactory before you destroy the TWICImage you will get access violations next time you call this procedure. (Have a look at TWICImage .Destroy).
  3. David Heffernan

    How to manage defined list values

    I use a cache, a dictionary keyed on the type info pointer, iirc
  4. David Heffernan

    How to manage defined list values

    Yes http://docwiki.embarcadero.com/RADStudio/en/Attributes_(RTTI)
  5. Lars Fosdal

    How to manage defined list values

    Both. See updated post. Let me correct myself... With a record helper, the methods of the helper become part of the helped type. begin TProjectType.InitClass; // only for the second example var prj: TProjectType = ptMain; writeln(prj.Caption); writeln(ptMain.Caption) writeln(TProjectType.CaptionOf(ptMain)) end; all output the same string. Populating a combobox can be done like this for var prj := Low(TProjectType) to High(TProjectType) do ComboBox1.AddItem(prj.Caption, Pointer(Ord(prj))); and later, if you like such ugly hacks 😉 if ComboBox1.ItemIndex >= 0 then begin var selectedprj := TProjectType(Integer(ComboBox1.Items[ComboBox1.ItemIndex])); end;
  6. Lars Fosdal

    How to manage defined list values

    I prefer record helpers, combined with the const arrays. I really wish I could make generic record helpers for arrays, though 😕 type TProjectType = (ptMain, ptSub, ptExternalDev, ptInternalDev); TProjectTypeHelper = record helper for TProjectType private const cProjDefValues: array[TProjectType] of string = ('main_proj', 'sub_proj', 'dev_ext', 'dev_int'); cProjCaptions: array[TProjectType] of string = ('Main Project', 'Sub Project', 'External Dev Project', 'Internal Dev Project'); public class function DefValueOf(const aProjectType: TProjectType): string; static; class function CaptionOf(const aProjectType: TProjectType): string; static; function DefValue: string; function Caption: string; end; implementation { TProjectTypeHelper } function TProjectTypeHelper.Caption: string; begin Result := CaptionOf(Self); end; class function TProjectTypeHelper.CaptionOf(const aProjectType: TProjectType): string; begin Result := cProjCaptions[aProjectType]; end; function TProjectTypeHelper.DefValue: string; begin Result := DefValueOf(Self); end; class function TProjectTypeHelper.DefValueOf(const aProjectType: TProjectType): string; begin Result := cProjDefValues[aProjectType]; end; The class functions could also be case statements - but the array[type] ensures you have values for all. The weak spot here is if you insert a value in the constant list, or reorder values - without doing the same for the strings. Or you can use class vars - which would make it easier to load up different languages at runtime, if so needed. type TProjectType = (ptMain, ptSub, ptExternalDev, ptInternalDev); TProjectTypeHelper = record helper for TProjectType private class var cProjDefValues: array[TProjectType] of string; cProjCaptions: array[TProjectType] of string; public class procedure InitHelper; static; class function DefValueOf(const aProjectType: TProjectType): string; static; class function CaptionOf(const aProjectType: TProjectType): string; static; function DefValue: string; function Caption: string; end; implementation { TProjectTypeHelper } function TProjectTypeHelper.Caption: string; begin Result := CaptionOf(Self); end; class function TProjectTypeHelper.CaptionOf(const aProjectType: TProjectType): string; begin Result := cProjCaptions[aProjectType]; end; function TProjectTypeHelper.DefValue: string; begin Result := DefValueOf(Self); end; class function TProjectTypeHelper.DefValueOf(const aProjectType: TProjectType): string; begin Result := cProjDefValues[aProjectType]; end; class procedure TProjectTypeHelper.InitHelper; begin cProjDefValues[ptMain] := 'main_proj'; cProjCaptions [ptMain] := 'Main Project'; cProjDefValues[ptSub] := 'sub_proj'; cProjCaptions [ptSub] := 'Sub Project'; cProjDefValues[ptExternalDev] := 'dev_ext'; cProjCaptions [ptExternalDev] := 'External Dev Project'; cProjDefValues[ptInternalDev] := 'dev_int'; cProjCaptions [ptInternalDev] := 'Internal Dev Project'; end;
  7. David Heffernan

    TThread issue

    It's a bug for the very reasons that you raised! When the thread was created in the constructor of `TThread` it meant that you couldn't synchronise passing state to the thread before it started.
  8. David Heffernan

    TThread issue

    That was a bug fixed in Delphi 6, and one of the reasons for the introduction of AfterCreation. I never create threads suspended.
  9. Dalija Prasnikar

    TThread issue

    Actually, there is no race condition because thread is actually started in AfterConstruction. So you can put just about anything you need in thread constructor and create thread in non suspended state.
  10. Fr0sT.Brutal

    How to manage defined list values

    I prefer the 1st. But keep in mind that most of hard-coded constants could require changing to run-time assignments if you want multi-language support
  11. The first approach ensures a single caption and defvalue for each value of tprojecttype due to the array structure. With the list approach you could add multiple entries for one value of tprojecttype. You could replace the TList with a TDictionary. This way you can easily access the strings attached to the specific value of TProjectType. A third solution that I prefer is the use of a record helper for TProjectType. Then you can use ptMain.Caption and ptSub.DefValue. The additional strings are closely connected to TProjectType.
  12. Remy Lebeau

    Sending Email via GMail Using OAuth 2.0 via Indy

    Indy does not currently support OAuth yet. However, it would be fairly simple to create a TIdSASL-derived component that can be added to the TIdSMTP.SASLMechanisms collection to transmit an OAuth bearer token using the SMTP "AUTH XOAUTH2" command. But getting that token in the first place is the tricky part, and has to be done outside of SMTP.
  13. Anders Melander

    ANN: Better Translation Manager released

    @Vandrovnik A new version with the Duplicate View is now available: http://melander.dk/download/amTranslationManagerInstall-1.0.7254.4932.exe I had a bit of trouble getting this version up as BitDefender kept insisting that amResourceModuleBuilder.exe contained the Gen:Variant.DCry.1 ransomware. In the end I had to simply include the previous version of that file instead. Description of the Duplicate View above. I have also included the "Locate in TM action: As the hint says, the action attempts to locate the focused source/target pair. It tries to be a bit intelligent about it in case there are multiple candidates (due to sanitation/equalization) so it will give priority to exact matches, case insensitive matches, sanitized matches and equalized matches, in that order. If a match is found the TM is opened and the matching row is selected: This version also includes Copy to clipboard (as CSV) and Save to CSV. Next up is Paste and Import from CSV.
  14. Anders Melander

    ANN: Better Translation Manager released

    Done. The action performed on values to check for equality isn't called equalization though. It's called normalization. Internally, in the source, I call it Sanitation (i.e. I remove all the junk). Anyway, here's what I have implemented: The "duplicate view" is invoked via the popup menu: When viewing duplicates a new column is added. This column displays the sanitized value of the selected language. You can control what sanitation rules to apply. Only rows that have duplicate values are displayed in duplicate view. In case you wonder why I'm not grouping on the Duplicate column; I tried it but found that it just cluttered the user interface and made the grid too cumbersome to navigate. I'll try to get a new version with these changes released tomorrow or Tuesday. I understand the problem. The dialog is already trying to communicate too much information and has become too complex for a standard message dialog. I have already redesigned it a bit (see below) but in order to add a "Replace" action I would have to switch to using a full blown Task Dialog or even better a custom dialog. That however will have to wait. I think the best I can do in the short term is to add a "Find in TM" action. This would open the TM, try to locate the currently focused Source/Target value pair and focus the target value in the TM.
  15. Rollo62

    Tlabeledit for fmx

    Not sure what you require, maybe that helps as base, but its VCL ? In FMX you simply can drop label on edit or vice-versa, to create a combined component. With layout align and margins you can do a lot.
  16. eivindbakkestuen

    Ann: NexusDB Spring Sale

    Hi, and welcome to NexusDB's "Spring Cleaning Down Under" Sale! Until end of Monday 18th November, take 33% off any purchase of new licenses. Use coupon code SPRING2019 during checkout to receive your discount. Sale extends to all NexusDB database products, and Nexus Quality Suite. Don't miss out. Oh, and if you are overseas, you also benefit from the weak AUD currency, which means right now you just can't get better value for your money. 🙂 www.nexusdb.com regards, The NexusDB Team
  17. WPTools is a complete WYSIWYG word processing control which does not add a huge overhead to your program. It loads and saves RTF, HTML, text and its own native format. DocX import and export functionality is available as an add-on and, for PDF export, use our wPDF component. WPTools reliably supports editable headers and footers in its page layout mode. Zooming, splitscreen, tables - including the possibility of page breaks inside table rows - and a powerful concept with a CSS-like paragraph style are supported by the modern architecture. Optional support for footnotes, columns and text boxes is availabe in the Premium Edition. Please see our website and the WPTools 9 word processing EXE demo. WPTools 9 includes the improved component WPImagelist which holds the icons for the TWPToolbar. If you add the unit WPIcons to your project (i.e. in one uses clause) all TWPToolbars will automatically use the new, nicer icons. The color icons can now display the current color. You can use the WPImageList with the TWPToolButtons to create a modern GUI easily. The WPImageList can also populate a standard TImageList. WPTools 9 creates PropertyGrids To display an inspector like grid, you can use the new API AppendPropertyGrid and AppendPropertyRow. Support for inplace checkbox controls The check boxes can be automatically created within property grids. But they can also be added in code to any cell or text object. Internally they are based on a "InplaceEditor" architecture which will be subsequently extended and improved. Now it is possible to have round and square check boxes, also with radio button functionality. It is also possible to use an event to paint the appearance, i.e. by using gylphs from the TWPImageList. The extended properties used by the inplace editors can be saved in WPT format. Dynamic Tables (TableProducer component - included in WPTools "Bundle") Do you need to present the user the result of a database query and also print it? With WPTools' dynamic tables the user can not only browse the result of the query, but also change the appearance of the table and the data cells and print it in WYSIWYG manner. In contrast to "data-grid" solutions, it is also possible to copy part of the created tables and paste them directly into a word processor program, such as MS Word or, of course, TWPRichText. Improved, more intuitive API Many low level TParagraph methods return a reference of the used paragraph. This makes compact and easy to understand coding possible. There is now also a simplified variant of TableAdd() which works with an anonymous procedure as callback New possibility to automatically direct all character attribute changes to the attributes of the paragraph If axtivated, a change of the font of a paragraph will not change the current writing mode or the selected text but the paragraph(!) attributes directly. The effect is, that the complete paragraph will change. Also the character attributes will automatically cleared. We uses this feature in our TableProducer demo. Here the user can change the attributes of the lines with the field names and later this attribute will be used to update the table. So the user can directly change the background color or use a bold or italic font style. Support for the Windows Emoji Font. Symbol objects can now be rendered using Direct2D (on a temporary bitmap, for compatibility). This enables the colors in certain fonts, such as the Segoe UI Emoji font. The special rendering can be enabled using ViewOptionsEx2 and is also activated in the Insert-Symbol dialog for the font with the name in the variable WPDrawD2DTextForFont and can also be selected per object. Regards, Julian Ziersch WPCubed GmbH - www.wpcubed.com
  18. Correct. The base of the code from NumWords is just 70-somewhat lines and can easily be adjusted to follow the additional/proper rules. const Digits: array [1 .. 9] of string = ( 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'); Teens: array [1 .. 9] of string = ( 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen'); TenTimes: array [1 .. 9] of string = ( 'ten', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety'); function DoTriplet(TheNumber: Integer): string; var Digit, Num: Integer; begin Result := ''; Num := TheNumber mod 100; if (Num > 10) and (Num < 20) then begin Result := Teens[Num - 10]; Num := TheNumber div 100; end else begin Num := TheNumber; Digit := Num mod 10; Num := Num div 10; if Digit > 0 then Result := Digits[Digit]; Digit := Num mod 10; Num := Num div 10; if Digit > 0 then Result := TenTimes[Digit] + ' ' + Result; Result := Trim(Result); end; Digit := Num mod 10; if (Result <> '') and (Digit > 0) then Result := 'and ' + Result; if Digit > 0 then Result := Digits[Digit] + ' hundred ' + Result; Result := Trim(Result); end; function NumberInWords(TheNumber: Integer): string; var Num, Triplet, Pass: Integer; begin if TheNumber < 0 then Result := 'Minus ' + NumberInWords(-TheNumber) else begin Result := ''; Num := TheNumber; if Num > 999999999 then raise Exception.Create('Can''t express more than 999,999,999 in words'); for Pass := 1 to 3 do begin Triplet := Num mod 1000; Num := Num div 1000; if Triplet > 0 then begin if (Pass > 1) and (Result <> '') then Result := ', ' + Result; case Pass of 2: Result := ' thousand' + Result; 3: Result := ' million' + Result; end; Result := Trim(DoTriplet(Triplet) + Result); end; end; end; end; procedure TForm1.FormCreate(Sender: TObject); begin Showmessage(NumberInWords(2120229)); end;
×