Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations bkrike on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

vfpskin2 revisited

Status
Not open for further replies.

codetyko

Programmer
May 26, 2001
73
MY
I'm using VFP6 and has downloaded the vfpskin2 class. What a great idea and a boon to us not so skillful programmers. However, I managed to get it to work the first time and when I want to include it in my project, It gave me the error message: "Cant find config file or it is empty."

I modified the readskin methid in the class to "force" it to accept the skin name like this:

instead of

_filename=THIS.SKINname+".txt"

I use:
_filename="c:\store\skins\saphe.txt"


However, another error occurred with the message that "CreateRectRgn.prg" not found()

I understand from the previous threads in this forum has indicated that the function is contained in foxtools.fll. I have include d foxtool in my project, referenced the class in my project as suggested but to no avail. Surfed a link to Universal thread on vfpskin2 and followed every instructions. Still No luck. Any pointers? Wow, I've been asking a lot of questions this time around. Hope nobody is complaining.
 
codetyko,

With an application I used the skins class with (heavily modified though) I used the following...

_filename="skins\"+THIS.SKINname+".txt"

...the reason is that I included a folder named "skins" in my application directory where the exe is installed. This allowed the skins class to find the skins configuration file (text file with the same name as the skin but extension is txt). This is a better solution than hard coding the path such as you are doing.

As to the CreateRectRgn, I don't know if that is in foxtools or not (i doubt it) but the one in the VFP skins class is referring to an API call...

DECLARE INTEGER CreateRectRgn IN gdi32;
INTEGER X1, INTEGER Y1, INTEGER X2, INTEGER Y2

...you should see this API call being declared in the skinsetup method of the class. Then you must call this skinsetup method in your form, I believe in the Init event of the form but possibly the load (don't remember I modified mine and add it to the form in code along with a resizer class). Such as:

*!* make sure you have also set the skin name before calling...
thisform.Vfpskin21.SkinSetup()


Slighthaze = NULL

[ul][li]FAQ184-2483
An excellent guide to getting a fast and accurate response to your questions in this forum.[/li][/ul]
 
After a few failed attempts, I finally got it to work and I thought I should share what I have accomplished. It may not be the best way to do it but as long as it works with no apparent performance overload, I think it should be of no consequence.

1) create a public variable named "skinnam" in the main prog as the 'default' value of your skin.

2) assign skinnam a value of one of the skinname e.g skinnam='closh'

3) copy the API declaration from the init() of the vfpskin2 class to your main program. (To ensure that it is declared since I could not get the init() of the vfpskin2 to "fire")

look for these statements:

*-*-*-* Declaro las funciones APIs -*-*-*-*-*-*-*-*-*-*-*-*

DECLARE INTEGER DrawEdge IN user32;
INTEGER hdc, STRING @qrc,;
INTEGER edge, INTEGER grfFlags

DECLARE INTEGER CombineRgn IN gdi32;
INTEGER hDestRgn, INTEGER hSrcRgn1, INTEGER hSrcRgn2,;
INTEGER nCombineMode
DECLARE INTEGER CreateRectRgn IN gdi32;
INTEGER X1, INTEGER Y1, INTEGER X2, INTEGER Y2
DECLARE INTEGER GetWindowDC IN user32 INTEGER HWND
DECLARE INTEGER GetFocus IN user32
DECLARE INTEGER ReleaseDC IN user32;
INTEGER HWND, INTEGER hdc
DECLARE INTEGER DeleteObject IN gdi32 INTEGER hObject
DECLARE INTEGER GetCursorPos IN user32 STRING @ lpPoint
DECLARE INTEGER SetWindowRgn IN user32 ;
INTEGER HWND, INTEGER hRgn , INTEGER bRedraw
DECLARE INTEGER GetPixel IN gdi32;
INTEGER hDC, INTEGER X, INTEGER Y
**----------------------------------------------------------**


4) alter the following in the vfpskin2 class



readskin() method in the class

add or alter:

THIS.skinname=skinnam
_filename=MAINDIR2+"skins\"+THIS.SKINname+".txt" where maindir2 is declared in your main prg as your default directory.


5) save the class

6) Put the modified class in your form. Set the "rskin" property to .t. or vfp7 with .t. or .f. as appropriate.



7) Insert the following command in every form you wish to have the skin in the init() method of the form:

thisform.Vfpskin21.skinname=skindir+skinnam where "skindir" is defined in your main program as skinndir='c:\store\skins\'


The above workaround works with no apparent overhead in performance. In order for this to work, all forms, foxtools must be in the project and compiled. There is no need to include the text files for the skin or the respected bmps.

Thank you slighthaze for the insight on the init method. I should have explored that earlier. Hope this may help other programmers in achieving a much improved look in our screen design. You can also create a separate form to include a picklist of all available skin files in your "skindir" and all you need to do is replace the "skinnam" value with the new value (minus the ".txt" extension) and execute the chgskin() method and voila!, a new skin will appear.
 
codetyko,

I did something similar to what you have laid out. In the load event of the form I placed the following lines

With This
.AddObject( 'Vfpskin21', 'vfpskin2')
.Vfpskin21.skinname = g_sSkinType
.Vfpskin21.SkinSetup()
endwith


If memory serves me correct there was an unnecessary call to the form's init event inside the VFPSkins2 class that I removed and I modified the paths to the skins themselves somewhat in the manner you have laid out.

I also created a form that would allow the user to change the skin or even remove the skin ("STANDARD") while the application was running. There is a combobox on the form that holds all of the skin names and when the user selects one and saves it sets the g_sSkinType variable and then runs this code...

FOR i = 1 TO _screen.formcount
WITH _screen.forms(i)
IF UPPER(g_sSkinType) != "STANDARD"
If Type(".Vfpskin21") != "O"
blnWasVisible = .visible
.AddObject( 'Vfpskin21', 'vfpskin2')
.Vfpskin21.skinname = g_sSkinType
.Vfpskin21.SkinSetup()
.refresh()
.Visible = blnWasVisible
ELSE
.vfpskin21.skinname = g_sSkinType
.vfpskin21.changeskin()
Endif
ELSE
blnWasVisible = .visible
.vfpskin21.deleteskin()
.RemoveObject("vfpskin21")
.refresh()
.Visible = blnWasVisible
ENDIF
ENDWITH
ENDFOR


In case you are wondering, I used the following code to populate the combobox mentioned above with all the skin names...I have a folder named SKINS in my application directory and client_path points to the application directory:


=ADIR(aryskins, client_path+"skins\*.TXT")
arylength = ALEN(aryskins)
FOR i = 1 TO arylength STEP 5
thisform.cmbskins.additem(PROPER(JUSTSTEM(aryskins(i))))
ENDFOR
***For Removing Skin - Show VFP default screens
thisform.cmbskins.additem("Standard")


I made a number of other modifications to the VFPSkin2 class that would take a little too much time and space to go into here (Maximize button to say Restore Down in tooltip when maximized, added resizer class to handle all of the controls on the screen, automatic _screen.backcolor change so the background looks like it goes with the skin the user has chosen, etc.)

Slighthaze = NULL

[ul][li]FAQ184-2483
An excellent guide to getting a fast and accurate response to your questions in this forum.[/li][/ul]
 
slighthaze, what has been provided should be more than adequate. thank you for sharing. A star for you.
 
codetyko,

If you gave me a star Tek-tips didn't wanna give it to me. :) Thanks for the interesting thread and good luck with the skins. Nice effect and an evolving class to be sure.

Slighthaze = NULL

[ul][li]FAQ184-2483
An excellent guide to getting a fast and accurate response to your questions in this forum.[/li][/ul]
 
Can addition VFPSKIN2 class into main foxpro windows, If yes, How?
 
ZooMoo,

Are you looking to add it to the _screen object? Or did you just mean how do you add it to a form?

Slighthaze = NULL
craig1442@mchsi.com
"Whom computers would destroy, they must first drive mad." - Anon​
 
Slighthaze, I mean add vfpskin class to _screen object, And a new problem of vfpskin, when i add vfpskin class in form it work correctly and not any effect to any another form or anothor program, But when using vfpskin class with ActiveX (*.ocx) will take incorrect ,or when call a form or a program using ActiveX after the form of activeX release it be take incorrent on the next form.

message error is API call caused and exception.
and look atdebugger found error in line ...
lnHwnd = _WhToHwnd( _WFindTitle( ..... in vfpskin readskin method.

 
I have made one directory named vfpskin and saved all the configuration files as well as class files and bmps in that directory related to vfpskin 2.0
Then in the form, I added class, changed rskin to .t. and vfp7 to .t. evenif I am using vfp 8.0
Then in skinname property of vfpskin21 I have written red.
Also I have changes some code in class as....
_filename=".\vfpskin\"+THIS.SKINname+".txt"

Now I run my form and it doesn't give any error to me but no skin is been shown. Instead the side portion of my form get erased about half inch from all side.

What's the problem?

Please help

Thanks and regards
 
zoomoo,

message error is API call caused and exception.
and look atdebugger found error in line ...
lnHwnd = _WhToHwnd( _WFindTitle( ..... in vfpskin readskin method.


I'm not sure about the caused of the error, but as far as the command is concerned, it's basically correct and I don't see any error in it. However, there is a workaround for your error:

In the INIT event of the form issue the command:

WITH THISFORM
.oskins.init()
.refresh
ENDWITH

In the INIT event of the class, look for this commands and insert the command as noted in the double ampersands.

IF THIS.vfp7=.F.
ON ERROR api_error = 0 && insert this command
SET LIBRARY TO foxtools.fll ADDITIVE
lnHwnd = _WhToHwnd(_WFindTitl(THIS.PARENT.CAPTION))
THIS.formhwnd = lnHwnd
ON ERROR && insert this command
ELSE
THIS.Formhwnd=THIS.PARENT.HWND
ENDIF

The purpose of the ON ERROR api_error = 0 command is just to continue the program and will not stop due to errors.

Save the class and rerun your program.


Bren
VFP - Philippines
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top