[Mono-winforms-list] Project status of WinForms on MacOS

Brock Reeve Brock.Reeve at ni.com
Wed Nov 7 14:25:35 EST 2007


Ok. I have looked into this some more and am getting the button to draw 
somewhat. The middle part isn't drawing correctly. I got this to work 
running a simple test program in C and compiled on the Mac. 

The graphics object doesn't give access to the raw quartz handle 
(CGContext) which is created in Graphics.FromHwnd and set on 
GDIPlus.Display static variable. The only way I could get it was to copy 
the code from Carbon.GetCGContextForView and use that in my drawing code 
for my button. I think this might be screwing it up somehow because I am 
creating another CGContext when one was already created for the Graphics 
object. Maybe we could support IServiceProvider or something on the 
Graphics object so we could query for the CGContext. There is another 
issue where if you click on the button it fails to draw again. Here is the 
code for the button and a screen shot. I am just experiementing for now 
putting the code in the button OnPaint rather than the Theme stuff.

public class CarbonButton : Button
    {
        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);
        }

        protected override void OnPaint(PaintEventArgs pevent)
        {
            Draw(pevent);
        }

        private void Draw(PaintEventArgs pargs)
        {
            Rectangle winRect = pargs.ClipRectangle;
            pargs.Graphics.DrawRectangle(Pens.Red, winRect);
            HIRect hiRect = new HIRect();
            Carbon.HIViewGetBounds(Handle, ref hiRect);

            CarbonContext cgContext = Carbon.GetCGContextForView (Handle);

            Console.WriteLine(hiRect.origin.x);
            Console.WriteLine(hiRect.origin.y);
            Console.WriteLine(hiRect.size.height);
            Console.WriteLine(hiRect.size.width);
            Console.WriteLine(winRect);

            HIThemeButtonDrawInfo buttonInfo = new 
HIThemeButtonDrawInfo();
            buttonInfo.state = ThemeDrawState.kThemeStateActive;
            buttonInfo.kind = ThemeButtonKind.kThemePushButton;

            HIThemeDrawButton(ref hiRect, ref buttonInfo, cgContext.ctx, 
kHIThemeOrientationNormal, IntPtr.Zero);
        }

        [StructLayout(LayoutKind.Sequential)]
        internal struct HIThemeButtonDrawInfo
        {
            public uint version;
            public ThemeDrawState state;
            public ThemeButtonKind kind;
            public ThemeButtonValue value;
            public ThemeButtonAdornment adornment; 
            public double start;
            public double end;
        }

        internal struct HIThemeAnimationTimeInfo
        {
            public double start;
            public double current;
        }

        internal struct HIThemeAnimationFrameInfo
        {
            public uint index;
        }

        internal struct Animation
        {
            public HIThemeAnimationTimeInfo time;
            public HIThemeAnimationFrameInfo frame;
        };

        internal enum ThemeDrawState : uint
        {
            kThemeStateInactive = 0,
            kThemeStateActive = 1,
            kThemeStatePressed = 2,
            kThemeStatePressedUp = 2,
            kThemeStatePressedDown = 3
        };


        internal enum ThemeButtonKind : ushort
        {
            kThemePushButton = 0,
            kThemeCheckBox = 1,
            kThemeRadioButton = 2,
            kThemeBevelButton = 3,
            kThemeArrowButton = 4,
            kThemePopupButton = 5,
            kThemeDisclosureButton = 6,
            kThemeIncDecButton = 7,
            kThemeSmallBevelButton = 8,
            kThemeMediumBevelButton = 3,
            kThemeLargeBevelButton = 9
        }

        internal enum ThemeButtonValue : ushort
        {
            kThemeButtonOff = 0,
            kThemeButtonOn = 1,
            kThemeButtonMixed = 2,
            kThemeDisclosureRight = 0,
            kThemeDisclosureDown = 1,
            kThemeDisclosureLeft = 2
        }

        internal enum ThemeButtonAdornment : ushort
        {
            kThemeAdornmentNone = 0,
            kThemeAdornmentDefault = (1 << 0),
            kThemeAdornmentFocus = (1 << 2),
            kThemeAdornmentRightToLeft = (1 << 4),
            kThemeAdornmentDrawIndicatorOnly = (1 << 5)
        }

        //ThemeOrentation
        private const uint kHIThemeOrientationNormal = 0;
        private const uint kHIThemeOrientationInverted = 1;

 
[DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
        internal static extern void HIThemeDrawButton(ref HIRect rect, ref 
HIThemeButtonDrawInfo info, IntPtr CGContext, uint themeOrientatino, 
IntPtr outLabelRect);
    }
}



Brock




Geoff Norton <gnorton at novell.com> 
11/02/2007 08:58 AM

To
Brock Reeve <Brock.Reeve at ni.com>
cc
mono-winforms-list <mono-winforms-list at lists.ximian.com>
Subject
Re: [Mono-winforms-list] Project status of WinForms on MacOS






Brock,

> I have been playing with your stuff on the Mac. Basic things are
> working and I am impressed. I am also impressed with the whole
> WindowsForms cross platform effort thus far. We have tested some of
> our custom WindowsForms components on Linux and for the most part
> things work (we haven't done exhastive testing. Have submitted a few
> bugs). 

I'm very glad to hear you have things working in the current state. :)

> I have a question about supporting the MacOS aqua stuff. I know the
> WindowsForms stuff has the Theme classes that do the drawing, but that
> seems to be a lot of work to draw all this stuff using GDI+. I was
> playing around with DrawThemeButton in the Carbon stuff to try and
> draw a themed button. My current approach (which is not working) was
> to derivie from Button and draw in OnPaint by calling DrawThemeButton
> from there. I am new to the Mac API's (Carbon and Cocoa) but I think
> the MacOS only allows drawing at certain times. From examples of
> DrawThemeButton, they put the call inside of the event loop callback's
> kEventControlDraw (we have that code in XplatUIOSX.cs). I haven't
> tried this solution but it is obviously not the right place to put the
> call because all the drawing is abstracted out into the Theme
> classes. 

The way this should be tackled is to use the HITheme APIs in HIToolkit
(thanks Stefan), instead of DrawTheme*.  These should be able to paint
out of loop for you.  We support out of loop painting already in MWF
(with a few caveats) so it is indeed possible.  I would suggest starting
with a simple theme that extends the Win32 one but overrides Button for
instance and calls HIThemeDrawButton. 

Take a look through HIToolbox/HITheme.h for more information on HITheme,
its a public supported API as of 10.4

-g


-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.ximian.com/pipermail/mono-winforms-list/attachments/20071107/810033d9/attachment-0001.html 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: screenshot.tiff
Type: image/tiff
Size: 25330 bytes
Desc: not available
Url : http://lists.ximian.com/pipermail/mono-winforms-list/attachments/20071107/810033d9/attachment-0001.tiff 


More information about the Mono-winforms-list mailing list