

PeterBelow
Members-
Content Count
569 -
Joined
-
Last visited
-
Days Won
13
Everything posted by PeterBelow
-
SudokuHelper is an application that acts like an electronic Sudoku grid. It supports 9x9, 12x12, and 16x16 Sudokus, both in the classic and Gosu variant, where cells can be marked to only accept even numbers. The application neither creates Sudokus itself nor provides a solver for them; it is just a more convenient way to solve a Sudoku from a magazine or other external source than doing it on paper, using pencil and eraser. The application's main features are: Invalid cell values are marked in red. Candidate values can be added and removed from a cell. Setting a cell's value will automatically remove candidates no longer possible in other cells. All actions can be undone, the undo stack is only limited by available memory. Named marks can be set for the current undo stack state and one can later restore the stack to such a named mark. The complete Sudoku can be saved to file, including the undo stack, and later loaded again from such a file. The project can be found on GitHub: https://github.com/PeterBelow/SudokuHelper The code is a good example (IMO) of how to uncouple the UI from the "buisness" code using interfaces, in a kind of MVC design. It is free (public domain) without restrictions.
- 38 replies
-
- interfaces
- uncoupled design
-
(and 2 more)
Tagged with:
-
Paste file from clipboard to blob field (Remote Desktop)
PeterBelow replied to Fivecord's topic in VCL
Google for "ole drag and drop delphi", that may turn up something useful. -
Are you looking for something like this? {! <summary> Remove all characters in aSet from the passed string and return the resulting string</summary>} function RemoveCharsInSet(const S: string; const aSet: TSysCharset):string; var I: Integer; begin Result := S; for I := Length(S) downto 1 do if S[I] in aSet then Delete(Result, I, 1); end; {! <summary> Remove all characters considered whitespace from the passed string and return the resulting string</summary>} function RemoveWhitespace(const S: string):string; const Whitespace = [#0..' ']; begin Result := RemoveCharsInSet(S, Whitespace); end;
-
Perhaps, but keep in mind that for MS developer tools are not the major part of their business by far, so the comparison is a bit unfair.
-
Well, there are heaps of sites that claim to do just that, just google for "life expectancy calculator"
-
It's difficult to make predictions, especially if they concern the future :). What may be important to know for you is this, however: The licence for the community edition cannot be renewed; if you need to install it on a new computer you need to get a new licence key, which is no problem, however. When a new Delphi/RAD Studio version comes out there is also a new community edition, usually available after a short delay. The previous version's community edition is then no longer available and you cannot get new licence keys for it anymore, so have to move to the latest edition if your old licence expires (it is limited to 1 year if memory serves).
-
I think the best way is to dissect the input into "words" and then assemble the parts you want from that list. procedure TForm1.Button1Click(Sender: TObject); var LWords: TStringlist; begin LWords := TStringlist.Create(); try LWords.Delimiter := ' '; LWords.DelimitedText := edit1.Text; if LWords.Count >= 2 then edit1.Text := LWords[0] + ' ' + LWords[1]; finally LWords.Free; end; end; Note that there also is a function PosEx(const SubStr, S: string; Offset: Integer): Integer in unit System.StrUtils that allows you to start the search at a position other than 1.
-
http://saxforpascal.sourceforge.net is quit good in my experience, I used it in a few projects a couple of years ago.
-
-
Well, TWebbrowser (in D11) has a protected method function GetEdgeInterface: TEdgeBrowser; To get at it you can use a cracker class, e.g. declared in the implementation section of the form unit containing the TWebbrowser control. type TWebBrowserCracker = class(TWebbrowser); In your code you can then do something like var Edge: TEdgeBrowser := TWebbrowserCracker(Webbrowser1).GetEdgeInterface; if Assigned(Edge) then begin Edge.UserDataFolder := SomeDirectory; Edge.ReinitializeWebView; end; Completely untested, so use at your own risk!
-
SudokuHelper - Example for uncoupled design via interfaces
PeterBelow replied to PeterBelow's topic in I made this
InternalHelperRegistry is a "global" variable declared in the implementation section of the unit and will stay around for the lifetime of the application; it is set to nil in the unit finalization. It has been some time since I last looked at the memory manager implementation, but a lock there does not protect against a race condition in the code assigning the resulting reference to a variable elsewhere.- 38 replies
-
- interfaces
- uncoupled design
-
(and 2 more)
Tagged with:
-
SudokuHelper - Example for uncoupled design via interfaces
PeterBelow replied to PeterBelow's topic in I made this
Well, interface references are pointers, so the problem is just how to make sure the reference count stays correct, which the code does. The singleton template the code was created from is quite old, however, predating the appearance of TMonitor by several years. There may be a cleaner way to implement this these days, but I don't like to change working code if there's no pressing reason to do so.- 38 replies
-
- interfaces
- uncoupled design
-
(and 2 more)
Tagged with:
-
SudokuHelper - Example for uncoupled design via interfaces
PeterBelow replied to PeterBelow's topic in I made this
That code comes from the forin template that comes with newer versions of Delphi. Sorry for the inconvenience, but since I program mostly for my own use i'm not much concerned with compatibilty with older Delphi versions and simply did not notice this as a potential problem.- 38 replies
-
- interfaces
- uncoupled design
-
(and 2 more)
Tagged with:
-
Pointers... loops...
PeterBelow replied to Sonjli's topic in Algorithms, Data Structures and Class Design
http://rvelthuis.de/articles/articles-pointers.html -
That sounds as if the form is no longer the foreground window after the ActiveX control hasloaded the file. Try to add a BringToFront; after the LoadFile line.
-
Just a guess: check the value of self.handle in both methods to verify they are the same. VCL forms are prone to recreate their window handle at the drop of a hat...
-
Did you remember to set the PopupMode property of your modal forms to pmAuto? What you describe sounds like a Z-order problem. But I see from the newer messages that the problem spontaneously resolved itself. It always makes me nervous when that happens in my projects...
-
Look at the Format function, it can be used to compose a string from values/variables using a template string with placeholders, taking the values to insert via an open array parameter. That covers all standard simple datatypes, but complex types like objects, arrays, dictionaries usually have no default method to convert their content to a string (although some have a ToString method, natively or through class or record helpers). For your own classes you can override the ToString method inherited from TObject, for instance.
-
Maake sure you set the form borderstyle to bsNone, so it has no caption bar. Windows does not like controls with the WS_Caption window style (and that is what the form becomes when you embed it), they have focus issues likr the one you observed.
-
Windows messages are lost when using SetTimer
PeterBelow replied to Clément's topic in Algorithms, Data Structures and Class Design
Timer messages have low priority. If your DoProcessMessages call takes longer than the message interval then a timer tick will not add a new wm_timer message to the queue but increment an internal count for the message already in the queue. Use a waitable timer and one of the MsgWait API functions instead of SetTimer, -
Well, there is a FileSearch function in Sysutils that will search for a file in semicolon-separated list of directory names, but of course you still have to extract the library path from the IDE settings (= registry key, specific for an IDE version), the search path from the current project, if relevant, replace any macros ($(name)) in the pathes etc. to get the list of folders. I'm not aware of a ready-made function for this exposed in the RTL or Open Tools API.
-
The Embarcadero GetIt server could not be reached...
PeterBelow replied to PeterPanettone's topic in Delphi IDE and APIs
https://community.idera.com/developer-tools/b/blog/posts/temporary-10-3-2-getit-server-for-installing-10-3-2-add-on-packages?fbclid=IwAR1bV79CCoutmAyH6slVbima_F9QMX29QX1nnwuCl5COCdmXU86BJJNhN9Y -
Conceptual - callbacks that are called from background thread
PeterBelow replied to Fr0sT.Brutal's topic in Algorithms, Data Structures and Class Design
Yes, it is far from easy to switch processing to a specific secondary thread. Basically it is only possible savely if that thread has been written for this. So i can only concur with your previous reply: the responsibility of handling the synchronizing should fall to the code providing the callback. -
handling predicate conditions
PeterBelow replied to David Schwartz's topic in Algorithms, Data Structures and Class Design
Yes, but the error you get then will not immediately indicate what the problem is. The way I do it its clear that the problem is a contract violation, and one can write unit tests that check whether the method correctly detects a contract violation. -
handling predicate conditions
PeterBelow replied to David Schwartz's topic in Algorithms, Data Structures and Class Design
I usually test for pre and postconditions like this: procedure TBlobDB.CreateNewDatabase(aDBStream, aIndexStream: TStream; aTakeStreamOwnership: boolean); const Procname = 'TBlobDB.CreateNewDatabase'; begin if not Assigned(aDBStream) then raise EParameterCannotBeNil.Create(Procname,'aDBStream'); if not Assigned(aIndexStream) then raise EParameterCannotBeNil.Create(Procname,'aIndexStream'); This is for errors that are supposed to be found and fixed during the testing phase or (for library code) in unit tests. For user input the input is validated before it is used by the program, if this is at all feasable. The end user should never see an exception coming from parameter validation at a lower level, in my opinion, since the UI context may not be evident at that point and it may be unclear to the user what he did wrong.