ToddFrankson 3 Posted December 17 So I have the ability to set the MACOS wallpaper on the current screen using this code (I believe Dave Nottage posted it). procedure SetDesktopBackground(const ImagePath: string; const FillColor: TAlphaColor); var NSFileURL: NSURL; NSWorkspace1: NSWorkspace; MainScreen: NSScreen; Error: NSError; begin try // Convert Delphi file path to NSURL NSFileURL := TNSURL.Wrap(TNSURL.OCClass.fileURLWithPath(StrToNSStr(ImagePath))); NSWorkspace1 := TNSWorkspace.Wrap(TNSWorkspace.OCClass.sharedWorkspace); MainScreen := TNSScreen.Wrap(TNSScreen.OCClass.mainScreen); // Set the desktop image for the main screen if not NSWorkspace1.setDesktopImageURL(NSFileURL, MainScreen, nil, @Error) then begin ShowMessage('Failed to set desktop image: ' + NSStrToStr(Error.localizedDescription)); end; except on E: Exception do begin ShowMessage('Error setting desktop image: ' + E.Message); end; end; end; My problem has been the 3rd parameter in SetDesktopImageURL..... Evidently it takes an NSDictionary. I have spent 3 days attempting to get this part to work with various attempts at translating ObjectiveC and swift code, using my brain and even several AI coding websites. Nothing I seem to do actually builds the dictionary. Can anyone lend me a hand? I have managed to find the following constants (Not defined in Delphi BTW): const NSImageScaleNone = 0; NSImageScaleAxesIndependently = 1; NSImageScaleProportionallyUpOrDown = 2; NSImageScaleProportionallyDown = 3; Here's the Dictionary documentation : https://developer.apple.com/documentation/foundation/nsdictionary?language=objc And the Documentation on the keys in the dictionary(Defined in the constants above): https://developer.apple.com/documentation/appkit/nsworkspace/desktopimageoptionkey?language=objc Thanks If someone could help me understand this, so I can get past it, I'd appreciate it. Share this post Link to post
Dave Nottage 563 Posted December 17 14 minutes ago, ToddFrankson said: I believe Dave Nottage posted it I did? 🙂 15 minutes ago, ToddFrankson said: My problem has been the 3rd parameter in SetDesktopImageURL.... This code works for me: procedure SetDesktopBackground(const ImagePath: string; const FillColor: TAlphaColor); var NSFileURL: NSURL; NSWorkspace1: NSWorkspace; MainScreen: NSScreen; LPointer: Pointer; Error: NSError; begin try // Convert Delphi file path to NSURL NSFileURL := TNSURL.Wrap(TNSURL.OCClass.fileURLWithPath(StrToNSStr(ImagePath))); NSWorkspace1 := TNSWorkspace.Wrap(TNSWorkspace.OCClass.sharedWorkspace); MainScreen := TNSScreen.Wrap(TNSScreen.OCClass.mainScreen); LPointer := nil; // Set the desktop image for the main screen if not NSWorkspace1.setDesktopImageURL(NSFileURL, MainScreen, nil, @LPointer) then begin Error := TNSError.Wrap(LPointer); ShowMessage('Failed to set desktop image: ' + NSStrToStr(Error.localizedDescription)); end; except on E: Exception do begin ShowMessage('Error setting desktop image: ' + E.Message); end; end; end; If you're having trouble creating a dictionary for the options, please show what code you attempted. Share this post Link to post
ToddFrankson 3 Posted December 18 1 hour ago, Dave Nottage said: I did? 🙂 This code works for me: If you're having trouble creating a dictionary for the options, please show what code you attempted. I think you posted it....I may be mistaken. Here is 1 variation: procedure SetDesktopBackground(const ImagePath: string; const FillColor: TAlphaColor); var Err: NSError; Options: NSMutableDictionary; ImageURL: NSURL; FillColorObj: NSColor; begin // Convert the image file path to NSURL ImageURL := TNSURL.Wrap(TNSURL.OCClass.fileURLWithPath(NSStr(ImagePath))); if ImageURL = nil then begin Showmessage('Failed to create NSURL for the image file.'); Exit; end; // Create a dictionary for desktop image options Options := TNSMutableDictionary.Wrap(TNSMutableDictionary.OCClass.dictionary); // Set the desktop image fill color FillColorObj := TNSColor.Wrap(TNSColor.OCClass.colorWithCalibratedRed( TAlphaColorRec(FillColor).R / 255, TAlphaColorRec(FillColor).G / 255, TAlphaColorRec(FillColor).B / 255, TAlphaColorRec(FillColor).A / 255)); Options.setObject(FillColorObj, NSWorkspaceDesktopImageFillColorKey); // Set the desktop image scaling to none Options.setObject(TNSNumber.Wrap(TNSNumber.OCClass.numberWithInt(NSImageScaleProportionallyUpOrDown)), NSWorkspaceDesktopImageScalingKey); // Set the desktop image for the main screen if not TNSWorkspace.Wrap(TNSWorkspace.OCClass.sharedWorkspace).setDesktopImageURL(ImageURL, TNSScreen.Wrap(TNSScreen.OCClass.mainScreen), Options, @Err) then begin if Err <> nil then Writeln(Format('Error setting desktop background: %s', [NSStrToStr(Err.localizedDescription)])); end; end; It hangs here: Options.setObject(FillColorObj, NSWorkspaceDesktopImageFillColorKey); Here is another: procedure SetDesktopColor(const Color: TAlphaColor); var Err: NSError; Options: NSMutableDictionary; URL: NSURL; TempFile: string; begin // Create a temporary file path for the color image TempFile := TPath.Combine(TPath.GetTempPath, 'SolidColorDesktop.png'); // Create a solid color image CreateSolidColorImage(Color, TempFile); // Load the image as an NSURL URL := TNSURL.Wrap(TNSURL.OCClass.fileURLWithPath(NSStr(TempFile))); if URL = nil then begin Showmessage('Failed to create NSURL for the temporary file.'); Exit; end; // Create a mutable dictionary for desktop image options Options := TNSMutableDictionary.Wrap(TNSMutableDictionary.OCClass.dictionary); // Set the desktop image fill color (not used in this case) Options.setObject(TNSColor.Wrap(TNSColor.OCClass.whiteColor), NSWorkspaceDesktopImageFillColorKey); // Set the desktop image scaling Options.setObject(TNSNumber.Wrap(TNSNumber.OCClass.numberWithInt(NSImageScaleNone)), NSWorkspaceDesktopImageScalingKey); // Set the desktop image for the main screen if not TNSWorkspace.Wrap(TNSWorkspace.OCClass.sharedWorkspace).setDesktopImageURL(URL, TNSScreen.Wrap(TNSScreen.OCClass.mainScreen), Options, @Err) then begin if Err <> nil then Showmessage(Format('Error setting desktop color: %s', [NSStrToStr(Err.localizedDescription)])); end; end; I have tried using NSDictionary in place of NSMutableDictionary, and used the SetValue method. That gives me an Exception in the onButtonUp event deep in FMX code. I tried this to get the current settings: function GetCurrentDesktopImageOptions: TDictionary<string, string>; var Options: NSDictionary; KeyEnumerator: NSEnumerator; Key: Pointer; OptionKey: string; OptionValue: string; ResultDict: TDictionary<string, string>; begin ResultDict := TDictionary<string, string>.Create; try Options := TNSWorkspace.Wrap(TNSWorkspace.OCClass.sharedWorkspace) .desktopImageOptionsForScreen(TNSScreen.Wrap(TNSScreen.OCClass.mainScreen)); if Options <> nil then begin KeyEnumerator := Options.keyEnumerator; while True do begin Key := KeyEnumerator.nextObject; if Key = nil then Break; OptionKey := NSStrToStr(TNSString.Wrap(Key)); OptionValue := NSStrToStr(TNSString.Wrap(Options.objectForKey(Key))); ResultDict.Add(OptionKey, OptionValue); end; end; Result := ResultDict; except ResultDict.Free; raise; end; end; This returns absolutely nothing. What am I doing wrong? I'd love to pass the dictionary with the Scaled image, and background color in the dictionary. Apple documentation gives me a headache. I'm surprised I got this far..... Share this post Link to post
Dave Nottage 563 Posted December 18 1 minute ago, ToddFrankson said: Options := TNSMutableDictionary.Wrap(TNSMutableDictionary.OCClass.dictionary); This should be: Options := TNSMutableDictionary.Create; 5 minutes ago, ToddFrankson said: Options.setObject(TNSColor.Wrap(TNSColor.OCClass.whiteColor), NSWorkspaceDesktopImageFillColorKey); This should be: Options.setObject(TNSColor.OCClass.whiteColor, NSObjectToID(NSWorkspaceDesktopImageFillColorKey)); Since setObject takes pointer parameters, for both. The rest should follow the same rule. Incidentally, there's loads of examples of using an NSMutableDictionary in the Delphi source (as well as in Kastri) 1 Share this post Link to post