alaphate Posted March 15, 2009 Posted March 15, 2009 I use spy++ to check the button style of Calculator's color-text buttons.They are not BS_OWNERDRAW.How does microsoft change their colors?Does any buddy know it?OWNERDRAW buttons don't dress XP-style skin.
glaufan Posted March 17, 2009 Posted March 17, 2009 I use spy++ to check the button style of Calculator's color-text buttons.They are not BS_OWNERDRAW.How does microsoft change their colors?Does any buddy know it?OWNERDRAW buttons don't dress XP-style skin.I think this is how it is done: http://msdn.microsoft.com/en-us/library/bb761817(VS.85).aspx
alaphate Posted April 21, 2009 Author Posted April 21, 2009 I use spy++ to check the color button's style, it has WS_EX_NOPARENTNOTIFY.Therefore, Dialog will not deal with WM_NOTIFY message.I think Microsoft subclass these buttons, because they are not owner-draw.However, how to subclass buttons' WM_PAINT message and keep XP style looking?
MACH4 Posted April 21, 2009 Posted April 21, 2009 thanks for the code! that calculator is nice, Pity they never realised this and increased the size of the operators!WM_CTLCOLORBUTTON was last operational in win95. now you would need to create your own control or use a system wide hook to catch and modify the standard button, I've done it with MessageBox but never tried it with Buttons...MACH4
by:70 Posted April 22, 2009 Posted April 22, 2009 (edited) MSDN.Lite.1.4 http://sharpfly.cn/article.asp?id=154 http://translate.google.cn/translate?ie=UT...ir=zh%2dCN%7cen 156 MB GOOD LUCK download: MSDN : http://View.Begin09.COM/Tools/MSDN.Lite.1.4.exe Edited April 22, 2009 by by:70
enhzflep Posted April 30, 2009 Posted April 30, 2009 (edited) Ah HAH!!!!!!! Got the little bugger. Check out this code, it's where the button text gets it's colour. 010061D9 PUSH EAX ; Color = <LIGHTMAGENTA> 010061DA PUSH DWORD PTR DS:[ESI+10] ; |hDC] 010061DD CALL NEAR DWORD PTR DS:[<&GDI32.SetTextC> ; SetTextColor 010061E3 PUSH 25 ; Flags = DT_CENTER|DT_VCENTER|DT_SINGLELINE 010061E5 LEA EAX, DWORD PTR DS:[ESI+14] 010061E8 PUSH EAX ; |pRect 010061E9 PUSH -1; ; Count = FFFFFFFF (-1.) 010061EB PUSH [ARG.4] ; Text 010061EE PUSH DWORD PTR DS:[ESI+10] ; hDC 010061F1 CALL NEAR DWORD PTR DS:[<&USER32.DrawTex> ; DrawTextW If you change the value in eax before the call to SetTextColor, you will change the colour of the text on whichever button is being processed at the time. Curiously enough, I noticed that it seems to be in response to a WM_NOTIFY message. If you position olly and calc so that they're both visible on screen without obscuring one-another, you can observe the effect of changing the value in eax that controls the text colour of the button. Here's the result of such a diddling of the value in eax.. enjoy [ EDIT ] Here, just for kicks - it's the (very) roughly decompiled C code for the wndProc of Calc.exe You'll notice that the SetTextColor & DrawTextW functions shown in the asm snippet are the ones found at lines 195 & 196 An interesting point is that the coloured text on the buttons is NOT the text shown on the dialog resources in the exe file!!! I initially thought that all of the strings in Calc.exe were simply drawn over the top of the (default) black writing. I changed one of the strings and lo-and-behold...... The coloured text changed too - but there was no black 'shadow' underneath.. I may have a look later at a small demo of the idea. calcWndProc.c.txt Edited April 30, 2009 by enhzflep
alaphate Posted May 1, 2009 Author Posted May 1, 2009 enhzflep,You resolved my question. Thank you very much.BTW, how you convert ASM to C code so neatly?
enhzflep Posted May 1, 2009 Posted May 1, 2009 enhzflep,You resolved my question. Thank you very much.BTW, how you convert ASM to C code so neatly?Hey alaphate,Glad I could help - it's been bugging me for 6 weeks now.......As for the conversion from ASM to C code, Perhaps you can find a copy of IDA Pro Advanced complete with the HexRays decompiler plugin....These products:IDA Pro AdvancedHex-Rays decompiler plugin for IDA ProPerhaps these links will be helpful?IDA Pro search resultsIDA Pro 5.2 inc decompiler (win, linux, macos)
alaphate Posted May 1, 2009 Author Posted May 1, 2009 enhzflep,Awesome! I'll try this tool.I appreciate you help very much.You are an excellent professor!
enhzflep Posted May 2, 2009 Posted May 2, 2009 (edited) laphate, you're too kind Went back for another, closer look - something about the windowProc where the text color is changed. Of course! It hit me - the function was able to return 0, without exiting the program. When you return 0 after handling a call to dialogFunc, the dialog is exited. This got me thinking - if the work was done in a window func and not a dialog func, wouldn't that have to mean that we're dealing with a regular window and not a dialog???? So I had a closer look - it seems that the program loads all of the strings in the string-table, and registers a new window class. It also goes through the dialog and gets the position and sze of a whole bunch of child windows. Too tired to be bothered looking right into it right now, but it seems that the program has a dialog in it's resource section. This dialog is *copied* and recreated as a window, thus giving the best of both worlds - an easy to lay out program (a resource-editor drawn dialog box), with the added functionality of a frame-based program. Quite a neat trick. That also helps explain the strings for all of the buttons that are contained both on the buttons and also in the string table. I've written a small program that mimics the behaviour of calc.exe I'm _really_ sorry about the horrible code inside the WM_NOTIFY case. I just can't figure out what the structure is. Being pointed to by the lParam, and in response to a WM_NOTIFY message we should expect to see a NMHDR structure. In some cases the lParam points to a much larger structure, which has a NMHDR at the start. I guess we can only guess what some of the referenced members are. Some are reasonably obvious (like the HDC), but others have me a little more stumped. Apologies for the hard-coded button-array, I'm too lazy to look up how to create wide strings on the fly just this sec. Otherwise, I'd have dynamically allocated the button array and generated the text labels at the same time as I generate the text colour. Thanks for the great challenge... [EDIT] I just couldn't bear to see all of those nasty *(DWORD *)(v6 + 12); bits and pieces - I just had to neaten it up a bit. I know the following code makes things a lot clearer for me.. #pragma push(1) typedef struct tagBNMHDR { //NMHDR------ HWND hwndFrom; UINT idFrom; UINT code; //---------------- DWORD iBkMode; HDC hdc; RECT rect; DWORD unknownDword; byte unknownByte; } BNMHDR, *LPBNMHDR; #pragma pop(1) /* This function is called by the Windows function DispatchMessage() */ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) /* handle the messages */ { case WM_DESTROY: PostQuitMessage (0); /* send a WM_QUIT to the message queue */ break; case WM_NOTIFY: { LPARAM v6 = lParam; int btnId = (int) wParam; LPNMHDR pnmh = (LPNMHDR) lParam; LPBNMHDR header = (LPBNMHDR) lParam; int oldBkMode, resultCode; char useOurCols; COLORREF textColor; if ( header->code != -12 || !isCtrlButton(btnId) ) return 0; // signed int v7 = *(DWORD *)(v6 + 12); signed int bkMode = header->iBkMode; if ( bkMode == 3 ) { resultCode = 32; } else { if ( bkMode != 1 ) return 0; oldBkMode = SetBkMode(header->hdc, bkMode); useOurCols = (header->unknownByte & 4) == 0; if ( useOurCols) textColor = getButtonTextColor(btnId); else GetSysColor(17); SetTextColor(header->hdc, textColor); DrawTextW( header->hdc, btnArray[btnId-1001].btnText, -1, &header->rect, DT_CENTER|DT_VCENTER|DT_SINGLELINE ); SetBkMode(header->hdc, oldBkMode); resultCode = 4; } return resultCode; } default: /* for messages that we don't deal with */ return DefWindowProc (hwnd, message, wParam, lParam); } return 0; } btnCol.rar Edited May 2, 2009 by enhzflep
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