Jump to content

PeterBelow

Members
  • Content Count

    465
  • Joined

  • Last visited

  • Days Won

    13

Everything posted by PeterBelow

  1. PeterBelow

    Using translations in unit Consts with Delphi 10.4 VCL

    Definitely. It will also not work if you build your project with runtime packages.
  2. PeterBelow

    Comport Serial Port help

    Can't you read it one byte at a time? I'm not familiar with the component you use.
  3. PeterBelow

    Virus? How odd.

    I had a similar problem with Delphi Alexandria, McAfee would detect a freshly build Win32 debug EXE as virus and quarantine it before I could debug it under the IDE, but it would not flag the 32 bit release version of the same program and neither 64 bit debug or release versions. By the way: to send an EXE through a mail server put it into a ZIP file and password-protect that. The encryption done will make a virus scanner ignore it since it cannot identify the zipped file as executable. Some particularly paranoid mail servers will reject password-protected zip files for this reason, though.
  4. PeterBelow

    StringGrid Align Vertically

    You can use the OnDrawCell event to draw the cell content yourself any way you like. The stringgrid.Canvas has a TextRect method that supports aligning the text in the way you want.
  5. Here is an example from my old threading library code. FSignal is a TSimpleEvent the thread will signal when it has finished its work. {! Wait for the call to complete. Optionally we can process a subset of messages during the wait. That complicates the timeout handling, though, since the wait can be interrupted by messages.} function TAsyncCall.WaitForCompletion(TimeoutMSecs: Cardinal; ProcessMessages: Boolean): TWaitResult; var TargetTime, CurrentTime: int64; H: THandle; Ret: DWORD; function TimeRemaining: DWORD; begin if TimeoutMSecs = INFINITE then Result := INFINITE else begin CurrentTime := ToInt64(GetTickCount()); if CurrentTime > TargetTime then Result := 0 else begin Result := TargetTime - CurrentTime; if Result > TimeoutMSecs then Result := 0; // GetTickCount rolled over end; end; end; {! We want to block most user input here but allow paint messages to be processed and also non-client messages that relate to moving or minimizing the window to be acted upon. Timer messages are also processed! } procedure ProcessPendingMessages; var Msg: TMsg; const NSCMask = $FFF0; begin while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do case Msg.message of WM_KEYFIRST..WM_KEYLAST, WM_MOUSEFIRST..WM_MOUSELAST: ; // swallow WM_NCMOUSEMOVE..WM_NCLBUTTONDBLCLK: case Msg.wParam of HTCAPTION, HTMINBUTTON: DispatchMessage(Msg); end; {case} WM_SYSCOMMAND: case Msg.wParam and NSCMask of SC_MINIMIZE, SC_RESTORE: DispatchMessage(Msg); end; {case} else DispatchMessage(Msg); end; {case} end; begin EnsureSignalIsCreated; if FCompleted then Result := wrSignaled else if ProcessMessages then begin TargetTime := ToInt64(GetTickCount()) + TimeoutMSecs; H:= FSignal.Handle; Result := wrAbandoned; repeat Ret := MsgWaitForMultipleObjectsEx( 1, H, TimeRemaining, QS_ALLINPUT, 0); case Ret of WAIT_ABANDONED : Exit; WAIT_FAILED : Result := wrError; WAIT_TIMEOUT : Result := wrTimeout; WAIT_OBJECT_0 : Result := wrSignaled; WAIT_OBJECT_0+1: ProcessPendingMessages; end; {case } until Result <> wrAbandoned; end {if} else Result := FSignal.WaitFor(TimeoutMSecs); end;
  6. PeterBelow

    Detect when user clicks down on scrollbar button?

    If the OnScroll event of the control is not sufficient for your need you have to subclass the control using its WindowProc property. Here is a short example using a TListbox filled with enough items to show a scrollbar as victim. The form also needs a TMemo to show the message traced. Note a few things regarding VCL subclassing: You need to find a place where the control you want to subclass has been created and that will only execute once during form creation. I used an overloaded Loaded method. The subclassing should be undone before the form is destroyed. A good place for that is an overloaded BeforeDestruction method. The replacement windowproc must pass all unhandeled messages to the original or the control will stop working. Usually one also passes the message one wants to handle to the original proc, perhaps with modified message parameters. type TMainform = class(Tform) ListBox1: TListBox; Memo1: TMemo; private FListWndProc: TWndMethod; procedure NewListboxProc(var Message: TMessage); protected procedure Loaded; override; public procedure BeforeDestruction; override; end; .... function GetScrollCodeAsText(aScrollcode: Smallint): string; begin case aScrollcode of SB_LINEUP: Result := 'SB_LINEUP'; SB_LINEDOWN: Result := 'SB_LINEDOWN'; SB_BOTTOM: Result := 'SB_BOTTOM'; SB_ENDSCROLL: Result := 'SB_ENDSCROLL'; SB_PAGEUP: Result := 'SB_PAGEUP'; SB_PAGEDOWN: Result := 'SB_PAGEDOWN'; SB_THUMBPOSITION: Result := 'SB_THUMBPOSITION'; SB_THUMBTRACK: Result := 'SB_THUMBTRACK'; SB_TOP: Result := 'SB_TOP'; else Result := 'unknown'; end; end; procedure TMainform.BeforeDestruction; begin if Assigned(FListWndProc) and Assigned(ListBox1) then Listbox1.WindowProc := FListWndProc; inherited; end; procedure TMainform.Loaded; begin inherited; if Assigned(ListBox1) then begin FListWndProc := Listbox1.WindowProc; Listbox1.WindowProc := NewListboxProc; end; end; procedure TMainform.NewListboxProc(var Message: TMessage); begin try if Message.Msg = WM_VSCROLL then begin memo1.Lines.Add( Format('Scroll code: %d (%s), position: %d', [TWMVScroll(Message).ScrollCode, GetScrollCodeAsText(TWMVScroll(Message).ScrollCode), TWMVScroll(Message).Pos ])); end; finally FListWndProc(Message); end; end; A click on the scrollbar thump (still in the top position) results in three messages: Scroll code: 5 (SB_THUMBTRACK), position: 0 Scroll code: 4 (SB_THUMBPOSITION), position: 0 Scroll code: 8 (SB_ENDSCROLL), position: 0
  7. PeterBelow

    Detect when user clicks down on scrollbar button?

    OnMessage only triggers for posted messages (PostMessage), but WM_VSCROLL is send (SendMessage). Using an OnSCroll event, if the control offers one, is the preferred way, though.
  8. PeterBelow

    Detect when user clicks down on scrollbar button?

    Yes, in a VCL control, at least. The control wll receive WM_VSCROLL messages when the user manipulates the scrollbar. The message parameters tell you what has happened.
  9. PeterBelow

    Codesite auto-invoke not working?

    Have you tried to check "Select shortest matching symbol"?
  10. PeterBelow

    PopUp Sub-Menu Location

    The position of the submenus is controlled by Windows (assuming we are talking about a VCL app), by default it pops up on the right side, unless there is insufficient space available on the screen on that side. I don't know of a way to control that. What you could do is to implement each submenu as a separate TPopupMenu and pop it up manually from the OnClick event of the "parent" menu item. Unfortunately it is not trivial to determine the screen position of an open menu item...
  11. PeterBelow

    Delphi 10.4 missing XML Data Binding

    With my Delphi 10.4 Version 27.0.37889.9797 (Professional) it is found under File->New->Others, Delphi projects, Web:
  12. Modelmaker CodeExplorer (MMX) offers that, and a lot of similar stuff for quickly adding methods etc. And it's free now. Could not live without it...
  13. PeterBelow

    task thread priority?

    Windows is not a real-.time OS, so you don't have any guarantee for defined thread execution times, and your program has to share the CPU resources with a few dozen OS processes. Anyway, your problem sounds like you flood your UI thread's message queue with update requests (you do Synchronize these request, I hope, and do not execute the background task's work in a syncronized method). These requests have a higher priority than the paint messages your changes to the UI cause to be added to the queue. If adding calls to a method like procedure ProcessPaintrequests; var Msg: TMsg; begin while PeekMessage(Msg, 0, WM_PAINT, WM_PAINT, PM_REMOVE) do DispatchMessage(Msg); while PeekMessage(Msg, 0, WM_NULL, WM_NULL, PM_REMOVE) do DispatchMessage(Msg); end; does not fix the problem you have to lower the priority of your worker threads to give the main thread more time to update the UI.
  14. A kind of transaction log saved to local storage (a file) may serve your purpose. You can write entries to a file using a write followed by a flush operation (or a full open - write - close cycle) . While not very fast it will ensure the entry is either written completely or not all (if the PC suffers a power failure, for example). Your operation would then follow this scheme: Write the intent to print, with the ID of the item to print, to the log print the item write the success of the operation to the log save it to the database write an end of transactio to the log or delete the log On (re)start the program can then look for a transaction log and analyse it to see how far it got on the last run.
  15. PeterBelow

    DelphiCon 2021 Code Examples

    At least one of the examples is on github: https://github.com/gustavomenabarreto/delphicon2021 Perhaps you can find more in the replays on Youtube: DelphiCon 2021 Playlist It's probably up to the speakers to make the code for their talk available somewhere...
  16. In this case it is, but one should never make assumptions about in which order the parts of a complex expressions are evaluated. It may even change depending on compiler flags, e.g. optimization on or off, stack frames on or of, range and overflow checks.
  17. PeterBelow

    Delphi profiler

    Set the Capacity property of your list objects to a suitably high value before you start adding objects, that can greatly improve performance since it cuts down cases where the list has to grow its internal array.
  18. PeterBelow

    Interface question

    @David IMO you are mixing data with UI in a way that only causes problems. You should use a list class instance (nonvisual) to hold objects that represent a student, each of which holds a list of the classes taken with the score obtained. The list class can then have a method to compose the items for a listview you pass as parameter to the method. If you need that you can store the reference to the student object in the corresponding listitem's Data property, but the lifetime management of the objects is the duty of the list class, not that of the UI listview.
  19. PeterBelow

    calculete time in delphi

    DecodeTime is the wrong method to use since it decodes a time point, not a time interval. The System.Diagnostics.TStopwatch record may be of more use for your problem. Add a private field FStopwatch: TStopwatch; to your form. In the OnCreate event you start the stopwatch with FStopwatch := TStopwatch.StartNew; When you want to know the elapsed time call FStopwatch.Stop first and then examine the Elapsed property. It returns a TTimespan record, which has properties to dissect the time interval into days, hours, minutes etc.
  20. PeterBelow

    TControlList - Jump to Selected

    Tcontrollist inherits the ParentBackground property but does not publish it, it is protected. You can try to set it to true in code, using a cracker class: type TControllistCracker = class(TControllist); ... TControllistcracker(Controllist1).Parentbackground := true; Untested!
  21. PeterBelow

    SplitString

    There is nothing wrong with the code you posted, other than the comma instead of semicolon after the "string" in the var section. Perhaps you have another SplitString function closer in scope than StrUtils.SplitString here. If you hover the mouse over SplitString, what does the code insight popup tell you where it's from?
  22. 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.
  23. PeterBelow

    Paste file from clipboard to blob field (Remote Desktop)

    Google for "ole drag and drop delphi", that may turn up something useful.
  24. PeterBelow

    Trim

    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;
×