LCF-AT Posted April 3, 2019 Posted April 3, 2019 Hi guys, I would like to know whether anyone knows a method to create rounded corners (buttons / Icons) filled with gardient colors inside and transparent outside the corners.At the moment I didnt found any way to make it with a simple method.Only thing I could do is to fill each outside pixel manually with some color xy. Example: Using static color of menu (no gardient style) I create a context menu with drawed icons before each menu entry.Now I draw the background with same color like the menu has and then creating the round corners. ............... invoke GetSysColor,COLOR_MENU ; get system menu color invoke CreateSolidBrush,eax push eax invoke FillRect,hdcBitmap,addr rect,eax ; fill icon rect 16x16 with menu color pop eax invoke SelectObject,hdcBitmap,eax invoke RoundRect, hdcBitmap, rect.left, rect.top, rect.right, rect.bottom, 6, 6 .............. The result looks so... ...this works. Example: Doing same with Gardient color invoke Gradient_Fill,hdcBitmap,addr rect,084ACDDh,0ECF5FFh,GRADIENT_FILL_RECT_V invoke GetStockObject,HOLLOW_BRUSH invoke SelectObject,hdcBitmap,eax invoke RoundRect, hdcBitmap, rect.left, rect.top, rect.right, rect.bottom, 6, 6 ...result like this... ....if you check the corners outside then you still see the colors... ....I dont wanna have.Only way I could do is to fill each single outside pixel of the corners manually using FillRect function like this.... invoke Gradient_Fill,hdcBitmap,addr rect,084ACDDh,0ECF5FFh,GRADIENT_FILL_RECT_V invoke GetStockObject,HOLLOW_BRUSH invoke SelectObject,hdcBitmap,eax invoke RoundRect, hdcBitmap, rect.left, rect.top, rect.right, rect.bottom, 6, 6 invoke GetSysColor,COLOR_MENU INVOKE CreateSolidBrush,eax mov SYSCOLOR,eax mov rect.bottom,0 mov rect.left,0 mov rect.right,2 mov rect.top,1 INVOKE FillRect, hdcBitmap, ADDR rect, SYSCOLOR mov rect.bottom,0 mov rect.left,0 mov rect.right,1 mov rect.top,2 INVOKE FillRect, hdcBitmap, ADDR rect, SYSCOLOR mov rect.bottom,16 mov rect.left,0 mov rect.right,2 mov rect.top,15 INVOKE FillRect, hdcBitmap, ADDR rect, SYSCOLOR mov rect.bottom,16 mov rect.left,0 mov rect.right,1 mov rect.top,14 INVOKE FillRect, hdcBitmap, ADDR rect, SYSCOLOR mov rect.bottom,0 mov rect.left,14 mov rect.right,16 mov rect.top,1 INVOKE FillRect, hdcBitmap, ADDR rect, SYSCOLOR mov rect.bottom,0 mov rect.left,15 mov rect.right,16 mov rect.top,2 INVOKE FillRect, hdcBitmap, ADDR rect, SYSCOLOR mov rect.bottom,16 mov rect.left,14 mov rect.right,16 mov rect.top,15 INVOKE FillRect, hdcBitmap, ADDR rect, SYSCOLOR mov rect.bottom,16 mov rect.left,15 mov rect.right,16 mov rect.top,14 INVOKE FillRect, hdcBitmap, ADDR rect, SYSCOLOR ....result.... ...so it works but its a bad method using so much single FillRects for this for the outside pixels.Does anyone has any clue how to make the pixel outside transparent etc when using RoundRect function?Or is there any Gardient Round Fill function I could use? greetz
LCF-AT Posted April 30, 2019 Author Posted April 30, 2019 Hi again, so I still have the problem using RoundRect & GradientFill function.This time I am trying to make some ownerdraw buttons with round corners what looks like this... ...is there no way or method to un-fill this outside corner areas without filling those pixels manually? greetz
Teddy Rogers Posted May 1, 2019 Posted May 1, 2019 You need to set a clipping path for drawing rounded rectangles and filling with a gradient. It is only a few lines of code so fairly straight forward. BeginPath_(bmpHDC) RoundRect_(bmpHDC, r\left, r\top, r\right, r\bottom, 128, 128) EndPath_(bmpHDC) SelectClipPath_(bmpHDC, #RGN_COPY) GdiGradientFill(bmpHDC, @pVertex(), 2, @pMesh, 1, #GRADIENT_FILL_RECT_V) Full PB example code is in the spoiler below and I have attached working example for you... Spoiler ; GdiGradientFill is not recognised by default in PureBasic so we need to declare and map the function. Global gdi32 = OpenLibrary(#PB_Any, "Gdi32.dll") Prototype.i GdiGradientFill(hdc, *pVertex, nVertex, *pMesh, nCount, ulMode) Global GdiGradientFill.GdiGradientFill GdiGradientFill = GetFunction(gdi32, "GdiGradientFill") ; Set the inner rectangle working area for drawing and clipping. r.RECT r\top = 1 r\left = 1 r\bottom = 239 r\right = 299 ; A pointer to an array of TRIVERTEX structures that each define a triangle vertex. Dim pVertex.TRIVERTEX(1) pVertex(0) \x = r\left pVertex(0) \y = r\top pVertex(0) \Red = RGB(255, 248, 220) pVertex(0) \Green = RGB(255, 248, 220) pVertex(0) \Blue = $0 pVertex(0) \Alpha = $ffff pVertex(1) \x = r\right pVertex(1) \y = r\bottom pVertex(1) \Red = RGB(222, 184, 135) pVertex(1) \Green = RGB(222, 184, 135) pVertex(1) \Blue = $0 pVertex(1) \Alpha = $ffff ; An array of GRADIENT_RECT structures in rectangle mode. pMesh.GRADIENT_RECT pMesh\UpperLeft = 0 pMesh\LowerRight = 1 If OpenWindow(0, 0, 0, 300, 240, "RoundedRect + GdiGradientFill...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) ; Create a bitmap we can start drawing on to. srcHDC = GetDC_(#Null) bmpHDC = CreateCompatibleDC_(srcHDC) bmpIMG = CreateCompatibleBitmap_(srcHDC, 300, 240) SelectObject_(bmpHDC, bmpIMG) ; Pick a background colour and fill the bitmap with it. FillRect_(bmpHDC, @r.RECT, GetStockObject_(#WHITE_BRUSH)) ; Select a clipping path for our rounded rectangle then clip it and fill it with a gradient colour. BeginPath_(bmpHDC) RoundRect_(bmpHDC, r\left, r\top, r\right, r\bottom, 128, 128) EndPath_(bmpHDC) SelectClipPath_(bmpHDC, #RGN_COPY) GdiGradientFill(bmpHDC, @pVertex(), 2, @pMesh, 1, #GRADIENT_FILL_RECT_V) ; Set the background and text colour for drawing text on to the bitmap. SetBkMode_(bmpHDC, #TRANSPARENT) SetTextColor_(bmpHDC, #Red) ; Select an appropriate font and then draw the text. hFont = CreateFont_(r\bottom, r\right, 0, 0, #FW_BOLD, 0, 0, 0, #ANSI_CHARSET, #OUT_DEFAULT_PRECIS, #CLIP_DEFAULT_PRECIS, #DEFAULT_QUALITY, #DEFAULT_PITCH|#FF_DONTCARE, "Impact") SelectObject_(bmpHDC, hFont) DrawText_(bmpHDC, "1", -1, @r.RECT, #DT_CENTER | #DT_VCENTER) DeleteObject_(hFont) ; Set the background brush to be our bitmap. hBrush = CreatePatternBrush_(bmpIMG) SetClassLongPtr_(WindowID(0), #GCL_HBRBACKGROUND, hBrush) InvalidateRect_(WindowID(0), 0, #True) ; Wait for the window to be closed. Repeat Event = WaitWindowEvent() Until Event = #PB_Event_CloseWindow ; Delete used objects and handles before we finish up. DeleteDC_(bmpHDC) ReleaseDC_(#Null, srcHDC) DeleteObject_(bmpIMG) DeleteObject_(hBrush) CloseLibrary(gdi32) EndIf Ted. RoundedRect + GdiGradientFill.exe 1
LCF-AT Posted May 1, 2019 Author Posted May 1, 2019 Hi Ted, thanks for that new info.So I tried it but I got some issues.So the rounded corners are not same rounded on all 4 corners.They differ from each other when I am using the new functions.... invoke BeginPath,[esi].hdc invoke RoundRect,[esi].hdc,[esi].rcItem.left,[esi].rcItem.top,[esi].rcItem.right,[esi].rcItem.bottom,6,6 invoke EndPath,[esi].hdc invoke SelectClipPath,[esi].hdc,RGN_COPY Do you see.The corners differ and on right below corner was nothing done.If I dont use the functions above then RoundRect does work right on all 4 corners. All 4 corner should be same.Next problem is that I also wanna draw the outside frame / line with RoundRect.Now if I play a little around with the new functions I get only this result...using RoundRect twice... invoke RoundRect,[esi].hdc,[esi].rcItem.left,[esi].rcItem.top,[esi].rcItem.right,[esi].rcItem.bottom,6,6 invoke BeginPath,[esi].hdc invoke RoundRect,[esi].hdc,[esi].rcItem.left,[esi].rcItem.top,[esi].rcItem.right,[esi].rcItem.bottom,6,6 invoke EndPath,[esi].hdc invoke SelectClipPath,[esi].hdc,RGN_COPY Somehow it dosent match.I dont know why the RoundRect inside of new functions are working else.Do you know why and how to manage this now? greetz
Teddy Rogers Posted May 1, 2019 Posted May 1, 2019 You will need to give me a bit more info on the first problem. How are you filling the round rectangle area and when? Regarding the second problem. After filling the rectangle create a pen and define its width, PS_SOLID should work fine. Then select it for the device context and then redraw the round rectangle... Pen = CreatePen_(#PS_SOLID, 2, $0) SelectObject_(bmpHDC, Pen) RoundRect_(bmpHDC, r\left, r\top, r\right, r\bottom, 128, 128) Ted. 1
LCF-AT Posted May 1, 2019 Author Posted May 1, 2019 (edited) Hi again, I have created a Pen before & did select it into hdc.After this I am calling your functions as I did post above.Problem is the RoundRect what dosent round same on all 4 corners as you can see in my pics above.If I dont use your functions then RoundRect works as it should.Maybe you can check this out.Just create a normal button with BS_OWNERDRAW flag and at WM_DRAWITEM do the roundrect / color stuff. Example: Just do this like I did.Just to check the roundrect thing. mov esi,_lparam assume esi:ptr DRAWITEMSTRUCT .if [esi].CtlType==ODT_BUTTON invoke CreatePen,PS_SOLID,1,0707070h invoke SelectObject,[esi].hdc,eax ; This RoundRect using for the frame ;invoke RoundRect,[esi].hdc,[esi].rcItem.left,[esi].rcItem.top,[esi].rcItem.right,[esi].rcItem.bottom,6,6 invoke BeginPath,[esi].hdc invoke RoundRect,[esi].hdc,[esi].rcItem.left,[esi].rcItem.top,[esi].rcItem.right,[esi].rcItem.bottom,6,6 invoke EndPath,[esi].hdc invoke SelectClipPath,[esi].hdc,RGN_COPY ; GardientFill Function below invoke SL_FillRectGradient,addr [esi].DRAWITEMSTRUCT.rcItem,[esi].DRAWITEMSTRUCT.hdc,084ACDDh,084ACDDh,GRADIENT_FILL_RECT_V .endif As result I get this what you can see in the pics above where the roundrects are diffrent and not same.If I disable BeginPath,EndPath & SelectClipPath & GardientFill then RoundRect does work right and all 4 corners are same round.So where is the problem in this case? greetz EDIT: If I use Ellipse function instead of RoundRect between Begin & EndPath functions then I get this. All same.Just wonder why it dosent work same with RoundRect too. EDIT2: Listen,so if I use the function CreateRoundRectRgn instead of RoundRect then it works like this... ....all 4 corners right rounded with this function!=?But now I still have the problem to color the outline frame.So RoundRect dosent match for this again.Like this... mov esi,_lparam assume esi:ptr DRAWITEMSTRUCT .if [esi].CtlType==ODT_BUTTON invoke CreatePen,PS_SOLID,1,0707070h invoke SelectObject,[esi].hdc,eax ; for the outline frame invoke RoundRect,[esi].hdc,[esi].rcItem.left,[esi].rcItem.top,[esi].rcItem.right,[esi].rcItem.bottom,6,6 invoke BeginPath,[esi].hdc invoke CreateRoundRectRgn,[esi].rcItem.left,[esi].rcItem.top,[esi].rcItem.right,[esi].rcItem.bottom,6,6 invoke SelectObject,[esi].hdc,eax invoke EndPath,[esi].hdc invoke SelectClipPath,[esi].hdc,RGN_COPY ; GardientFill Function below invoke SL_FillRectGradient,addr [esi].DRAWITEMSTRUCT.rcItem,[esi].DRAWITEMSTRUCT.hdc,084ACDDh,084ACDDh,GRADIENT_FILL_RECT_V .endif ...I get this to see... ...so what I see is that RoundRect function does work strange inside of the Path function (without Path function RoundRect works right).Now I see I could use CreateRoundRectRgn instead of RoundRect which works but I need to draw the outline frame anyhow and correctly / matching.Do you have any idea for this task now? Edited May 1, 2019 by LCF-AT
Teddy Rogers Posted May 1, 2019 Posted May 1, 2019 I would check your gradient structure and rectangle work area dimensions are correctly sized. Make sure you have no other drawing events going on in the device context - before or after drawing the rectangle. Can you try drawing your bitmaps when your program starts up as it seems a bit unnecessary redrawing them on each WM_DRAWITEM event? If you are going to add frames remember to do this after you have filled the rectangle with your gradient... Ted. 1
LCF-AT Posted May 2, 2019 Author Posted May 2, 2019 Hi again, problem isnt the gardient struct so the same happens too if I dont use gardient function and just fill with any color using fillrect etc.I also dont have other drawings running in this example and just using the code I did post above already.The strange issues just happens while using the Path functions. Now I tried again around and found a working method using RoundRect & CreateRoundRectRgn + moving the rect a little.See my code below.The first add / sub before RoundRect I do to set the same Hight like the windows button have.After RoundRect I need to add 1 on top and 1 on left to be inside of the frame and for CreateRoundRectRgn I am using 3 & 3 = half of RoundRect 6 & 6 and now it works.Of course its again some kind of de-tour but as result I get a 100 % match for all buttons I do wanna change...... mov esi,_lparam assume esi:ptr DRAWITEMSTRUCT .if [esi].CtlType==ODT_BUTTON ;---frame color--- invoke CreatePen,PS_INSIDEFRAME,1, 0707070h invoke SelectObject,[esi].hdc,eax add [esi].DRAWITEMSTRUCT.rcItem.top, 1 sub [esi].DRAWITEMSTRUCT.rcItem.bottom, 1 invoke RoundRect,[esi].hdc,[esi].rcItem.left,[esi].rcItem.top,[esi].rcItem.right,[esi].rcItem.bottom,6,6 add [esi].DRAWITEMSTRUCT.rcItem.top, 1 add [esi].DRAWITEMSTRUCT.rcItem.left, 1 invoke BeginPath,[esi].hdc invoke CreateRoundRectRgn,[esi].rcItem.left,[esi].rcItem.top,[esi].rcItem.right,[esi].rcItem.bottom,3,3 invoke SelectObject,[esi].hdc,eax invoke EndPath,[esi].hdc invoke SelectClipPath,[esi].hdc,RGN_COPY invoke GardientFill...... .endif greetz
Teddy Rogers Posted May 3, 2019 Posted May 3, 2019 How are you drawing, to a bitmap or a DIB object? Ted.
LCF-AT Posted May 3, 2019 Author Posted May 3, 2019 Hi, what do you mean Ted?Above the code I am using for Buttons Ownerdraw at WM_DRAWITEM message.Just drawing into the hdc device of it.I am just using normal button with BS_OWNERDRAW flag.No bitmap etc. By the way.The code I did post above does work as I told already for my buttons and now I wanted also to update my code for my icons in a contextmenu to prevent drawing outside of the corners but in this case its not working same and the outside of corners are colored.Only if I use FillRect with COLOR_MENU color its working but I wonder why I have to use this function in this case and in the button case not!=?This I dont understand now.There so and here so!? In the button code example above using your Path functions I dont need to use FillRect function and the ouside of corners getting not filled with any color = Good as I wanted but the same piece of code dosent work for icons.... Example: Icons only on the left side invoke CreateCompatibleDC,NULL mov hdcBitmap,eax invoke GetDC,NULL mov hdcScreen,eax invoke CreateCompatibleBitmap,hdcScreen, 16, 16 mov hbm,eax invoke SelectObject,hdcBitmap, hbm mov hbmOld,eax mov rect.left,0 mov rect.top,0 mov rect.bottom,16 mov rect.right,16 invoke GetSysColor,COLOR_MENU invoke CreateSolidBrush,eax mov brush, eax invoke FillRect,hdcBitmap,addr rect,eax invoke SelectObject,hdcBitmap,brush invoke CreatePen,PS_INSIDEFRAME,1,Black mov pen, eax invoke SelectObject,hdcBitmap,eax invoke RoundRect,hdcBitmap, rect.left, rect.top, rect.right, rect.bottom, 6, 6 invoke BeginPath,hdcBitmap add rect.top, 1 add rect.left, 1 invoke CreateRoundRectRgn, rect.left, rect.top, rect.right, rect.bottom, 3, 3 mov RoundRectRgn, eax invoke SelectObject,hdcBitmap,eax invoke EndPath,hdcBitmap invoke SelectClipPath,hdcBitmap,RGN_COPY invoke SL_FillRectGradient,addr rect,hdcBitmap,084ACDDh,0ECF5FFh,GRADIENT_FILL_RECT_V Now i this picture you can see no color outside of corners (with using FillRect function above)... ....on next picture I didnt use FillRect function and I get this result to see... ....the question now I have is how to prevent using FillRect function with COLOR_MENU like I did with buttons?Lets say the Menubackground is also custom & colorful / gardient etc then I think that using COLOR_MENU will not match with the used menu background color etc you know what I mean?My goal in this case is it just using any round corners (button / icons / whatever) and to prevent drawing any color outside of the corners to keep them transparent. greetz
Teddy Rogers Posted May 4, 2019 Posted May 4, 2019 I was going to suggest - if you were using DIB - to call the GdiFlush function before you start drawing. Since you are using bitmaps I don't think using it will make any difference, you could try though. Can you send me a compiled version using the gradient function where it is not being correctly clipped? I will test something here. What OS are you using at the moment, Windows 7 x32? Ted.
LCF-AT Posted May 4, 2019 Author Posted May 4, 2019 Hi Ted, so I see that I need to use any FillRect function to fill the outside with any color X.If I dont use it then some color is still to see over the corners in icons or also in button areas.The problem is how to use FillRect function with the right color X the background does use.For example,if I use normal system menu then I need to use the color of COLOR_MENU to fill it with that color first or if I color the dialogbox background then I need to use this color to fill it first.So anyhow I need always to use FillRect with color X.I made a small file / source where you can see it like here.... ...so what is if I dont know the background color or what if the background using a gardient color style or any random color or bitmap or whatever?How to fill then? PS: Yes I am using x86 (32bit) W7.Below the exe file from picture above + source. OD_TEST.rar greetz
LCF-AT Posted May 6, 2019 Author Posted May 6, 2019 Hi again, just have a question again about filling with right colors. How to get the "actually" used background color of the main dialog and Menu Background? I see I can use GetSysColor function with COLOR_MENU flag and COLOR_3DFACE flag for dialog to get the system color values and using it with FillRect function.But how to get the colors of the background if I have changed the dialog & Menu background colors by myself?How to get then the right actually used colors?Just asking for this how to do that without to save the used background color values exta somewhere and using them.I tried to get the actually colors but failed to get the right one and only get the system color values not the used ones. greetz
Teddy Rogers Posted May 7, 2019 Posted May 7, 2019 If you are setting the colour scheme I do not understand why you do not want to store those colour values so you can retrieve them later. What is it that you are trying to achieve? Ted.
LCF-AT Posted May 7, 2019 Author Posted May 7, 2019 Hi Ted, just wanted to know whether there is any function where I can get the "actually" used color values anyway if I use default color sheme or modded color sheme.Similar like reading the content of a edit control = reading from edit control and not from stored string buffer etc you know. greetz
Teddy Rogers Posted May 8, 2019 Posted May 8, 2019 I am still not entirely sure what it is you are trying to achieve, I think you may be over-complicating things. If you are setting a custom colour scheme for a window and menus it will be much easier to access those colour values somewhere since you already know them. If you are owner drawing menus on each WM_DRAWITEM there will be no colour values to find unless they have been created. If you know the window coordinates or have a handle to a device context of a bitmap you could use GetPixel function... Ted. 1
LCF-AT Posted May 8, 2019 Author Posted May 8, 2019 Hi Ted, so it was just a question whether its possible to get actually used color by any function.So I tried it with some infos from internet and I always got the colors from default and not from actually used colors.Sure,if I would change the colors manually then I also could save them somewhere to know it and use it etc.As always I am just trying to find out what is possible you know (over-complicating maybe).The GetPixel function I tried too in the past but had no luck with that function and got other color values as they was used.I will try go on.Thanks again so far. greetz
LCF-AT Posted May 25, 2019 Author Posted May 25, 2019 Hi again, small new question about DRAWITEMSTRUCT and handle the itemState ODS_DISABLED.My question is how to draw the icon or whole entry in disabled style = Windows does gray it transparent anyhow.I would like to do this too or similar also with the icons I have made via CreateCompatibleBitmap etc.Have I put any transparent layer over it or something? greetz
Progman Posted May 26, 2019 Posted May 26, 2019 I remember how I looked at a lot of UI controls when the source code to Windows 2000 was leaked. It would have been nice to always start your owner drawing with the default Windows handling and then customize it as needed given that they handle all sorts of things like accessibility, etc in there which are easy to forget about or overlook. In this case, probably they are just using the system default transparency color which you can look up, and doing some sort of transparency mask with it possibly with a special brush pattern. A simple system call and GDI call but the exact manner of doing it would possibly require RE. Or you can go your own route and forget how Windows does it which has been the normal way. Have you taken a look at the Windows 2000 source code??? Probably it has your answer. 1
LCF-AT Posted May 26, 2019 Author Posted May 26, 2019 Hi Progman, so it would be nice to have / find some kind of complete Ownerdraw example template code but didnt found anything like that.Ony short codes to handle this or that you know.Also for a menu OD I didnt found any full code example / template to handle all situations for menus etc. No I didnt checked the Win 2000 source.Maybe I wouldnt also find where this OD code is stored into (file xy). greetz 1
Progman Posted May 26, 2019 Posted May 26, 2019 (edited) https://people.symlink.me/~rom1/dev/ windows_2000_source_code.zip\win2k\private\ntos\w32\ntuser\client - ZIP archive, unpacked size 658,114,889 bytes WinRAR can even search the archive for you if you don't want to extract it. menuc.c - however menu is really a combination of a check box button and a static control I think. btnctl.c - complete with owner draw example for buttons statctl.c - complete with owner draw example for statics SYSRGB(GRAYTEXT) seems to be referenced for disabled. Of course this is old source and by now they have rewritten and changed a lot with Aero and other features. But the core of Windows UI programming is still based off this which is why Microsoft continues to rigorously sanitize that leaked source from the web 20 years later!!! But I will solve this for you now for real: mngrayc.c - the entire drawing code for the draw state (sounds like menu gray to me). If this snippet is not allowed for wrath of MSFT then admin could kindly remove it... /* * Is our scratch bitmap big enough? We need potentially * cx+1 by cy pixels for default etc. */ if ((gcxGray < cx + 1) || (gcyGray < cy)) { if (hbmpT = CreateBitmap(max(gcxGray, cx + 1), max(gcyGray, cy), 1, 1, 0L)) { HBITMAP hbmGray; hbmGray = SelectObject(ghdcGray, hbmpT); DeleteObject(hbmGray); gcxGray = max(gcxGray, cx + 1); gcyGray = max(gcyGray, cy); } else { cx = gcxGray - 1; cy = gcyGray; } } PatBlt(ghdcGray, 0, 0, gcxGray, gcyGray, WHITENESS); /* * DISABLED state * Emboss * Draw over-1/down-1 in hilight color, and in same position in shadow. * * DEFAULT state * Drop shadow * Draw over-1/down-1 in shadow color, and in same position in foreground * Draw offset down in shadow color, */ if (uFlags & DSS_DISABLED) { BltColor(hdcDraw, SYSHBR(3DHILIGHT), ghdcGray, x + 1, y + 1, cx, cy, 0, 0, BC_INVERT); BltColor(hdcDraw, SYSHBR(3DSHADOW), ghdcGray, x, y, cx, cy, 0, 0, BC_INVERT); } else if (uFlags & DSS_DEFAULT) { BltColor(hdcDraw, SYSHBR(3DSHADOW), ghdcGray, x+1, y+1, cx, cy, 0, 0, BC_INVERT); goto DrawNormal; } else { DrawNormal: BltColor(hdcDraw, hbrFore, ghdcGray, x, y, cx, cy, 0, 0, BC_INVERT); } And then finally the work happens in BltColor with this line: BitBlt(hdc, xO, yO, cx, cy, hdcSrce, xO1, yO1, ((uBltFlags & BC_INVERT) ? 0xB8074AL : 0xE20746L)); //xO1, yO1, (fInvert ? 0xB80000 : 0xE20000)); So some really almost impossible to come up with on your own code with a 3D highlight/3D shadow and special hardcoded color inversion codes. And with Aero its probably 10 times worse if you need to support that. Have to decompile user32.dll in Win10 perhaps Why Visual Studio does not automatically generate the pages of original user32 code for you, I have no idea but it would sure make more professional consistent custom drawn Windows apps for sure!!! I hope a new source code leak comes soon I really liked the Win2k one - especially for the user32 code a real gem for those of us who have done owner drawing and want to exactly replicate original functionality without coming up with hacked up slightly incorrect alternatives. Edited May 26, 2019 by Progman 1
Progman Posted May 26, 2019 Posted May 26, 2019 Maybe you can rewrite some of your code based on what you find in there anyway. For me precise positioning and special effects like this are especially hard to figure out without the source. And when trying to make custom listview controls containing other controls and the like, its almost hopeless to make it professional without this. The abstraction versus efficiency never enabled them to generalize the UI code to avoid custom drawing and it was too intermingled with all their core UI source to possibly separate it out for distribution. They seem to be sacrificing efficiency now due to more powerful machines with UWP and such. 1
LCF-AT Posted May 27, 2019 Author Posted May 27, 2019 Hi Progman, do you mean that BltColor = BitBlt function? My code to set the menu icon in Ownerdraw is this.... Invoke CreateCompatibleDC, [edi].DRAWITEMSTRUCT.hdc mov hdcmem, eax Invoke SelectObject, hdcmem, Image mov hMenuBitmapOld, eax add bmprect.top,1 add bmprect.left,3 Invoke BitBlt, [edi].DRAWITEMSTRUCT.hdc, bmprect.left, bmprect.top, 16, 16, hdcmem, 0, 0, SRCCOPY sub bmprect.top,1 sub bmprect.left,3 Invoke SelectObject, hdcmem, hMenuBitmapOld Invoke DeleteObject, hMenuBitmapOld Invoke SelectObject, hdcmem, Image Invoke DeleteDC, hdcmem ...the Image variable is my icon handle what I made before via CreateCompatibleDC / CreateCompatibleBitmap.Not sure how to make it in disabled look.I also found a function called DrawState but failed anyhow to use it right etc. greetz
Progman Posted May 27, 2019 Posted May 27, 2019 Yes BltColor is a function whose work is essentially to call BitBlt but with the mask as mentioned. It should produce the disabled look if you use the code to do this with the hilight and shadow. But best you take a look at the original source code file as I have not actually tested this and just did a quick browse.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now