Jump to content

Anders Melander

Members
  • Content Count

    2297
  • Joined

  • Last visited

  • Days Won

    119

Everything posted by Anders Melander

  1. Anders Melander

    Rio and MDI Applications

    Yes I know about all the different opinions against MDI and while I agree with some of them that's not the topic of this thread. Also I think quoting Joel went out of vogue some 15 years ago
  2. Anders Melander

    Rio and MDI Applications

    Thanks. It's still a secondary source but I guess that if Embarcadero believes it to be canon then we have to work from that.
  3. Anders Melander

    Feature: ParentFont? Yes, but...

    Don't you think you've gone a bit overboard with the amount of font properties that can be handled? I mean: Both Size and Height? One is derived from the other. And in 25 years I don't think I've ever had to customize Quality or Pitch in the GUI... Charset, AFAIK, isn't needed with unicode.
  4. Anders Melander

    Rio and MDI Applications

    "is said to" = rumor The SO thread is just a lot of different opinions on MDI. Like this thread will probably become. Do you have any proof for that claim? I've seen it many, many times but never with any reliable sources. Also one would think that MS would document that fact, in the relevant API and concept documentation, like they usually do... I have several MDI applications that runs just fine on Windows 10. They're all based on DevExpress though and I don't know if they have done anything special to handle Win10 but I doubt it.
  5. Anders Melander

    Exception.CreateFmt vs. CreateResFmt

    Yes. I've only used this on 32-bit and I don't know if the structures are the same for 64-bit.
  6. Anders Melander

    Exception.CreateFmt vs. CreateResFmt

    That's fairly easy and you don't need to hack the system unit. You just need to patch the LoadStringW import. For example the following patches FindResourceW and a few others to implement a DFM fallback mechanism that loads from the main module in case the resource module doesn't contain a given DFM resource. It can easily be modified to patch LoadStringW to load resourcestrings from a dictionary or whatever. unit amLocalization.FindResourceFallback; interface function EnableResourceLoadingFallback: Boolean; implementation uses Windows; function HookAPI(const Name, Module: string; Hook: pointer): pointer; var ImageBase, Old: Cardinal; PEHeader: PImageNtHeaders; PImport: PImageImportDescriptor; PRVA_Import: LPDWORD; ProcAddress: Pointer; begin Result := nil; ImageBase := GetModuleHandle(NIL); PEHeader := Pointer(Int64(ImageBase) + PImageDosHeader(ImageBase)._lfanew); // pointer to the imports table of the main process: PImport := Pointer(PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress + ImageBase); // pointer to the WinAPI function we want to hook: ProcAddress := GetProcAddress(GetModuleHandle(PChar(Module)), PChar(Name)); if ProcAddress = NIL then Exit; while PImport.Name <> 0 do begin PRVA_Import := LPDWORD(pImport.FirstThunk + ImageBase); while PRVA_Import^ <> 0 do begin if PPointer(PRVA_Import)^ = ProcAddress then begin // initially imports table is in read-only segment: if not VirtualProtect(PPointer(PRVA_Import), 4, PAGE_READWRITE, Old) then Exit; Result := PPointer(PRVA_Import)^; // replacing import address with our own: PPointer(PRVA_Import)^ := Hook; // restoring old memory protection mode: if not VirtualProtect(PPointer(PRVA_Import), 4, Old, Old) then begin Result := nil; Exit; end; end; Inc(PRVA_Import); end; Inc(PImport); end; end; type TFindResourceW = function(hModule: HMODULE; lpName, lpType: PWideChar): HRSRC; stdcall; var FindResourceW: TFindResourceW = nil; function HookedFindResourceW(hModule: HMODULE; lpName, lpType: PWideChar): HRSRC; stdcall; begin Result := FindResourceW(hModule, lpName, lpType); if (Result = 0) and (hModule <> hInstance) then Result := FindResourceW(hInstance, lpName, lpType); end; type TLoadResource = function(hModule: HINST; hResInfo: HRSRC): HGLOBAL; stdcall; var LoadResource: TLoadResource = nil; function HookedLoadResource(hModule: HINST; hResInfo: HRSRC): HGLOBAL; stdcall; begin Result := LoadResource(hModule, hResInfo); if (Result = 0) and (hModule <> hInstance) then Result := LoadResource(hInstance, hResInfo); end; type TSizeofResource = function(hModule: HINST; hResInfo: HRSRC): DWORD; stdcall; var SizeofResource: TSizeofResource = nil; function HookedSizeofResource(hModule: HINST; hResInfo: HRSRC): DWORD; stdcall; begin Result := SizeofResource(hModule, hResInfo); if (Result = 0) and (hModule <> hInstance) then Result := SizeofResource(hInstance, hResInfo); end; function EnableResourceLoadingFallback: Boolean; begin FindResourceW := HookAPI('FindResourceW', kernel32, @HookedFindResourceW); Result := Assigned(FindResourceW); if (Result) then begin LoadResource := HookAPI('LoadResource', kernel32, @HookedLoadResource); Result := Assigned(LoadResource); end; if (Result) then begin SizeofResource := HookAPI('SizeofResource', kernel32, @HookedSizeofResource); Result := Assigned(SizeofResource); end; end; initialization EnableResourceLoadingFallback; finalization end.
  7. Anders Melander

    Exception.CreateFmt vs. CreateResFmt

    Constant resourcestring references are resolved during initialization by System._InitResStrings. If you change the application language after that, e.g. by calling LoadResourceModule, then these references will not be updated. In the example below the first ShowMessage in unaffected by the change of language while the second one isn't. resourcestring sFoo = 'Foo'; sBar = 'Bar'; const sFooBar: array[boolean] of string = (sFoo, sBar); sBetterFooBar: array[boolean] of PResStringRec = (@sFoo, @sBar); begin LoadResourceModule('foofoo.bar'); ShowMessage(sFooBar[True]); ShowMessage(LoadResString(sBetterFooBar[True])); end; Apart from that I suspect the RTL/VCL uses PResStringRec for C++ compatibility.
  8. Anders Melander

    Feature: ParentFont? Yes, but...

    For inspiration DevExpress controls have the standard ParentFont and individual properties to override font color and style (among other things) for Normal, Disabled, Focused and Hot state. There's also a style controller component so different styles can be configured centrally instead of on the individual controls.
  9. Anders Melander

    Why is ShowMesssage blocking all visible forms?

    Sounds like an example of doing something just because you can.
  10. Anders Melander

    Why is ShowMesssage blocking all visible forms?

    Um... Because it's a modal dialog. If it didn't block it wouldn't be modal.
  11. Anders Melander

    Interface Completion

    Are you asking if there's a way to have the Getter and Setter methods declared automatically from the property declaration in the interface declaration? E.g. you have: type IMyInterface = interface property Foo: string read GetFoo write SetFoo; end; and you want to end up with: type IMyInterface = interface function GetFoo: string; procedure SetFoo(const Value: string); property Foo: string read GetFoo write SetFoo; end; AFAIK there's no standard way to have the getters and setter automatically declared 😞 What I usually do, if there's a lot of them, is to just copy the property declaration to an implementing class, use class completion on that to generate the getters and setters and then copy the declaration of those back to the interface declaration.
  12. Anders Melander

    Generics and Classes on Windows 2000 = OOM

    Okay. Now the use of W2K makes much better sense. Interesting constraints. Anyway, back to the problem. If you can observe that virtual and physical memory consumption increases during execution, but all resources are released before the process is terminated (thus no leaks detected), then you can force the allocated memory to be reported as leaks by terminating the application prematurely with a call to Halt.
  13. Anders Melander

    Generics and Classes on Windows 2000 = OOM

    That makes good sense, but why limit virtual memory? Doesn't the devices have hard disks?
  14. You should probably rephrase that "and only slows me down". In my experience laziness always comes at a price. Not bothering to use descriptive identifiers saves a few keystrokes at the price of readability. ARC and GC relieves the developer of having to deal with some of the complexities of resource management, at the price of performance. Etc. I would honestly rather have good performance and full control of what's going on with the resources. Yes. Let's break COM support so we can save some keystrokes.
  15. How is that relevant to the topic?
  16. Anders Melander

    Generics and Classes on Windows 2000 = OOM

    FWIW, Windows 2000 isn't supported by the version of Delphi you're using. Also, please read the event log message again. It has all the clues: It isn't your application that is experiencing an "out of memory" error. It's Windows that is experiencing an "out of virtual memory" error. To fix it: Increase the size of the page file. My guess is that the W2K system has a fixed size page file - or no page file at all. Otherwise it would just increase the size automatically - or maybe that feature was added later. I forget. and who cares anymore. If you're really interested in why you get a windows error and not an application error, read some books on Windows internals and the virtual memory manager, or just google it.
  17. Anders Melander

    Image pointer and buffer size

    You're not giving us much to work with here. Do you have any documentation about what kind of data ReadFromMemFile expect the input buffer to hold?
  18. Anders Melander

    Image pointer and buffer size

    You didn't really answer @Vandrovnik's question. For Windows bitmaps the bitmap file image (i.e. bitmap header and pixel data) isn't stored in memory. When TBitmap loads a bmp file it reads the header information then the pixel data. From this it stores the relevant meta data (width/height, color depth, palette, etc) and pixel data in memory. Of these you only have direct access to the raw pixel data. If you need the file bitmap image in memory then you will either have to save the bitmap to a memory stream or construct the image yourself in memory. btw, when I write "image" I don't mean in the picture/graphic/bitmap sense. Maybe you should try to explain what problem you are trying to solve.
  19. Technically it's the page file. The terms page file and swap file have their roots in VMS. Both Windows NT and VMS were designed by his holiness, Dave Cutler. The swap file doesn't exist anymore in Windows (I believe it was there in early versions) but was used when a process working set was completely removed from physical memory. E.g. in low memory situations or if the process went into extended hibernation.
  20. No. You still don't understand the difference between physical and virtual memory.
  21. Please google "64-bit"
  22. True, but even in 2003 it was a 16-bit leftover from the DOS days.
  23. Please google "virtual memory".
  24. Anders Melander

    Anything sensible for source code documentation?

    Try Documentation Insight. It supports both XMLDOC (which I agree makes the source unreadable) and external documentation files: I've been using it to generate library help files (in CHM-format) but it can also display the help as tooltips in the Delphi editor.
  25. Anders Melander

    Why upgrade?

    What breaking changes are those? At one of my clients we upgraded all projects (many millions LOC) directly from Delphi XE & XE2 (for 64-bit) to Delphi 10.2 with no significant effort. The worst part was the tasks you'll have to do anyway every time you migrate a project from one version of Delphi to another. If they had kept up to date all the way through, they would have had to pay maintenance on 20+ licenses to get the occasional new feature they didn't really need and they would have had to fix and work around all the new bugs they got as well.
×