Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 07/16/19 in all areas

  1. This is more of a style thing, but please consider human readability and write while not Terminated do
  2. If you work with a TCanvas in background threads always wrap your code in canvas.lock; try ...operate on canvas here finally canvas.unlock; end; The VCL has a build-in mechanism to optimize use of GDI objects, which is shared between all TCanvases used, and his mechanism is not thread-safe. Locking the canvas makes sure it does not use this mechanism while it is locked.
  3. Remy Lebeau

    How to know that a file is not used by another program?

    The FileExists() check is unnecessary and should be removed. It introduces a race condition (the file may exist before FileExists() is called, and then gets deleted before CreateFile() is called) as well as a possible failure point (FileExists() is not 100% accurate in all possible situations, there are cases where it returns a wrong result). Calling CreateFile() by itself with OPEN_EXISTING is good enough. If the file really does not exist, CreateFile() will fail with an ERROR_FILE_NOT_FOUND error code. Also, your code does not take ERROR_SHARING_VIOLATION into account, which would mean the file is actually in use but you don't have access to open it. Try this instead: function IsFileInUse(FileName: TFileName): Boolean; var HFileRes: THandle; begin HFileRes := CreateFile(PChar(FileName), GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (HFileRes <> INVALID_HANDLE_VALUE) then begin CloseHandle(HFileRes); Result := False; end else Result := (GetLastError() = ERROR_SHARING_VIOLATION); end;
  4. In VCL, the TBitmap.Canvas must be locked while using the TBitmap in a worker thread. The RTL keeps track of all GDI resources it allocates, and the main UI thread runs a routine periodically that frees GDI resources that are not locked. Which is very bad for TBitmap used in a worker thread. The alternative is to not use TBitmap at all, just use the Win32 API directly for all GDI operations in a worker thread.
  5. Remy Lebeau

    What options do I have to control custom releases?

    You could put that information in your program's Version info. Define an .rc file that builds the version details conditionally. Then use compiler conditionals to control which features are turned on/off in code, and which details are shown/hidden in the version info when the .rc file is compiled.
  6. Clément

    What options do I have to control custom releases?

    Hi, There are a few options. Depending on your project, one might be a better choice than the other. (no particular order) 1) Use IFDEF. If you have a centralized unit where all those options are assigned, you can create in project manager a Release Customer A, Release Customer B,... , etc. In each project configuration option, you should add a conditional define such as __CUSTOMER_A__, __CUSTOMER_B__, ...etc. Your unit(s) will get a bunch of $IFDEFs : // control Main Menus {$IFDEF __CUSTOMER_A_} EnableVisioMenu := false;{$ENDIF} // Customer A {$IFDEF __CUSTOMER_B_} EnableDrawingMenu := false;{$ENDIF} // Customer B // control PopupMenu options EnableCntxt_ImportFromVision := {$IFNDEF __CUSTOMER_C} false {$ELSE} true{$ENDIF}; // ??? ... As you can see, the more customers you get, the more difficult it will be to maintain such spaghetti, but it gets the job done. 2) Use an encrypted external configuration file The file gets constructed according to each customer, the executable remains the same. The only difference is the config file. When you deliver your application, this file goes together. If you absolutely need to keep things in one file, you might consider generating a resource file (.RC) that will be included with your executable. Be aware that some anti-virus might show false positives. The file itself can be very simple, such as an INI file. As long as it's encrypted, it will do it's job. 3) More sophisticated license manager that will allow to handle properly many customers.
  7. Angus Robertson

    Help: Ics wrong recieve response app-json!

    It is better to process the response in the onRequestDone event. There is a new property added a year ago ResponseNoException which will help you. Angus
  8. No, you can operate on several canvases (of offline bitmaps or metafiles) in parallel, its is just a little bit less efficient since each canvas has to create its own font, pen, brush instead of using an existing one from the VCL sharing pool.
  9. Angus Robertson

    Help: Ics wrong recieve response app-json!

    Don't know what FConnectorUtils.StreamToString does, but you always have to seek to beginning of the stream before reading it. There is a new function that convert an HTML page in the buffer to unicode string with the correct codepage: FResponseRaw := IcsHtmlToStr(FResponseStream, FContentType, true); Last boolean option converts HTML entries like &pound; and &#9741; to unicode. That function is used in the new TSslHttpRest unit that hides a lot of the low level stuff you are doing returning Json. Angus
  10. Joseph MItzen

    RadStudio Roadmap 2019

    "...a single Language Server can be re-used in multiple development tools, which in turn can support multiple languages with minimal effort." In theory it would divorce the Delphi language from the Delphi IDE. This would allow for Delphi code completion and other features to be accessed from tools such as VS Code, Eclipse, Sublime Text and anything else implementing the protocol and enable supporting additional languages in the Delphi IDE. In theory. I can't shake the feeling that Embarcadero will find some way to lock things down. But the idea is really great and I've been advocating for this since the concept was first revealed by Microsoft and Red Hat.
  11. limelect

    change the path to an existing windows explorer

    @PeterBelow Thank you what i did in the above program just added 2 lines findexpl:=GetAncestor(WebBrowserApp.HWnd,GA_ROOT); SetForegroundwindow(findexpl);
  12. I have done an intensive debug session and found the issue although I don't understand why it works with older Delphi versions. At line 2710, where the server hang, we have the code: Result := GetOverlappedResult(FPipe, FOlapRead, FRcvRead, TRUE); I simply changed the last argument by FALSE like this: Result := GetOverlappedResult(FPipe, FOlapRead, FRcvRead, FALSE); And now it works! That last argument when TRUE tells GetOverlappedResult to wait until completion. If FALSE, it returns immediately with whatever data is available, setting FRcvRead variable with actual number of bytes read. Since we only go to that code line when data is available, because of WaitForMultipleObjects called at line 2939, we can safely don't wait for more data. I will do more testing with the actual - real world - application using that code. In case the issue persist, I will report it here. Thanks to all having participated in this conversation. -- François Piette Embarcadero MVP
  13. That's the name of the executing process. Asker wants to know about external processes.
×