Planet FoxPro

March 26, 2015

Sandstorm's Blog (Home of ssClasses)

SwitchX & OptionSwitchX - ssUltimate Library

What is SwitchX?

SwitchX is a descendant of ssSwitch.  It is my attempt to replace the old looking native checkbox of VFP.  Especially in this era of mobile devices, then something like this can be seen on android, Windows or IOS phones, where you can switch it on and off.


What is new?

Better designs, more themes.  I kept changing my designs over and over again where I retain the ones I like and replaces others I don't.  So definitely, some of the themes here will still change in the future; but you can safely guess which I will change later (the ugly ones, what I have shown below will be retained as those are among my fave).

Three new parameters, cToolTipText, nFontSize, cFontName.  I believe the names I used are self-explanatory enough.


What is OptionSwitchX

Well, this is the counterpart of the native OptionGroup of VFP.  I re-used here SwitchX so both will be receiving the same themes.

What is New?

Two new parameters,  cFontName, nFontSize 


OptionSwitchX Limition:

OptionSwitchX can only have a max 12 switches.  The reason for that is in my end, I rarely or never yet needs an OptionSwitchX or even the native OptionGroup with 12 buttons/switch.  So I believe it is more than enough.  Anyway, the codes are included when I release this library to the Subscribers so they can add more if they want.


Themes, where are those coming from?

All of those themes I design using Photoshop.  So you can do the same.  The themes images are stored on a separate class named ImagesSwitch so you can add more themes if you want.  Since I embed the images for extraction converting those into Base64 Binary, then you can use the Binary Block Breaker tool I shared last time for that need:  http://sandstorm36.blogspot.com/2012/06/binary-block-breaker-tool.html

Here are some of the themes, there are 20 themes right now:


Of course, the actual images are clearer and cleaner than the above because clarity is lost on conversion to a jpg format, and lost further during upload as those I believed were reduced further for faster viewing via web.  Plus the image is resized smaller.

by Jun Tangunan (noreply@blogger.com) at March 26, 2015 11:39 PM

ConX & ContainerX Classes - ssUltimate Library

ContainerX Class - Brief Introduction  

When I first started working on ssUltimate Library, I decided to create a counterpart of ssContainer there I called ContainerX.  This basically is just like ssContainer but with cleaner codes and better looking themes as the themes I used in ButtonX is also being utilized here.

In _ssClasses library, the image of ssContainer is dependent on your usage of ssButton for it is ssButton that takes care of generating the images.  So when you don't use ssButton, then ssContainer will also be useless as the images it needs won't be there, and you will get a big X which is the default appearance of an image object without any picture attached.

In ssUltimate, I created a separate custom class for the images extraction, and both classes has that custom class inside.  So those two, while still working with the same images, no longer relies with each other.



ConX Class, the difference


However, the design of ContainerX is into flashy embossed type.  So after I created TitleBarX, I decided to try giving my apps a flat look and while ContainerX fits just fine with my design concepts, I wanted then a really flat interface.  And so the creation of ConX (since I already used ContainerX, that is the simplest name that came to my mind to differentiate the two).

At first, all I wanted is something flat that looks cool  that can change color on the whim especially if it is tied up to TitleBarX.  Later, I decided to give this a capability to be turned into a button.  Still later, I decided to re-use  said class for my pageframe need.  It eventually became a 3-in-1 class that can be turned/utilized as plain container, a button, or a page tab.

Here is what it looks like, but first the parameters:
  • cCaption = The caption of the container, class tab section will auto-adjust based on parameters cCaption, cFontName and nFontSize
  • nColor = is the RGB() of your choice (or a shade using TitleBarX)
  • cFontName = font name
  • nFontSize = Font Size
  • nTabLeft = Whether you want the tab section at leftmost (default is 0), or you want it moved somewhere to the right (useful when making this as tab to create an illusion of a pageframe)
  • lInside = logical, whether you want an inside border or not (looks good for tabs, auto for tabs)
  • nCurve = curvature of the shape below tab section
  • nInBackColor = RGB() for that inside border/shape
  • lShowActive = Logical, whether you want to show a dotted shape as outline of the caption, useful in tabs
  • lNoTabs = When you are in the pageframe mode and you want only the active tab to be shown or not
  • cForeColor = Caption ForeColor 
There is another property that I left via using PEM called _nfunction.  By default, its value is 0 or class will be treated as a Container.  When you give this a value of 1, then class will become a button where it can receive a click event plus hover effect.  Turning the value into 3 will change the class' usage as a pagetab of a pageframe, sort of.

As a container (_nfuntion = 0)

Nothing much to be explained.  It is a container, plain and simple, with just a flashy caption and appearance.  It is where you can put objects inside it.

If you noticed on the above, I use titleBarX' power of shading there.


As a button (_nfunction = 1)

As mentioned, it will now receive a click event plus implement hover effect on mouse enter and leave.  Once it is turned as a button, then whatever objects you put inside is no longer individually clickable, only the class itself.



As a page tab (_nfunction = 3)

Now this is the trickiest usage of the class.  If you want to use this as a sort of pageframe, then you need to turn _nFunction = 3.  Not only that, if you want to mimic a pageframe, then you have to do this:

1.  Create an empty container on form, make the borderwitdh zero and make it transparent.
2.  For each tab, you use one ConX class.  So you can design your supposed to be tab outside, placing objects inside each container, and once you are done, you can put all those ConX classes inside the empty transparent container, one on top of the other.

Now, for me not to get confused on which tab I am working on, I change the backcolor of each (aside from the caption I set where I can place the name of the class as guide during developing time).  And when I need to reach the other conX to change something there, then I cycle through each via clicking Sent to Back button; until the one I want to work with goes on top.

3. You have to estimate the tab position of each conX based on the caption you will be placing via nTabLeft parameter, so each tabs can be seen.

4.  Decide whether to show all tabs all at once or only the active one via lNoTab parameter.  When you turn this into .T., then only the active tab can be seen at a time.  If the value is .F., then all tabs will be shown.

5.  You can choose to have different colored tabs or just a single color tab, your choice.  For a single color tab, then like I mentioned, this works hand-in-hand as well with TitleBarX so you can let TitleBarX give it a shade of its selected color.

6.  You can optionally show the Active Tab (it will be encased with dotted lines) via lShowActive parameter

Here is how it looks with only the active tab being shown at a time.  This image shows it being utilized as a tab and as a container (Finalize section).


Shown also above is SwitchX, ButtonX and otCalendar classes.

And how it looks like when all tabs are shown, varying colors: http://sandstorm36.blogspot.com.au/2015/02/for-eachendfor-gotcha.html


Forgive me for the colors I chose there, eventually I changed it into a single color that follows TitleBarX:

Well, I guess with this one, I will make a sample for my subscribers to see how to utilize said class based on those 3 _nFunction.  Especially on turning it into a pageframe, sort of.


Other more posts to come  for ssUltimate Library later are SwitchX, OptionSwitchX, ScrollTime, and StickyX; to name a few.

by Jun Tangunan (noreply@blogger.com) at March 26, 2015 05:59 AM

Alex Feldstein

Photo of the Day


Paper Kite (Idea leuconoe)
Fairchild Tropical Gardens

by Alex Feldstein (noreply@blogger.com) at March 26, 2015 05:00 AM

Sandstorm's Blog (Home of ssClasses)

ButtonX Class - ssUltimate Library

As much as I do not want to post here classes of ssUltimate that I retained strictly for my subscribers, since I no longer explain what changes I do now and then inside the library, then they have no way of knowing those; and therefore they are under utilizing it or does not know how to fully utilize it to their maximum advantage.

And so I decided that from now on, I will slowly post here those classes that remains hidden for others to serve as a guide for my Subscribers.  And to make it clear, those that are strictly for them will always have a suffix of - ssUltimate Library.

What is ButtonX?

ButtonX is my final button class which is the predecessor of ssButton series.  Any new features on a button class is done on this one.  This class is highly customizable based on the taste of the developer where you can change the position of the caption, change the theme, its color, etc.

What is new here?

It has better themes than its predecessors. Here are some of the themes, all with 6 colors to choose from, all with hover effect with color changing



Going Flat

Since flat seems to be the trend these days, I gave it new capability to become just like that, flat,  via the existing parameters plus 2 new parameters, i.e., nShpBackColor and nShpCurvature

To make it absolutely flat, all the user needs to do is to change the nTheme parameter into 0. Once you turn nTheme into zero, then it will ignore the existing built-in themes I designed as seen on the above image.  It will make those invisible.


But as you can see, the border is still there.  To turn it into really flat, turn nLineSpecialEffect paramater into 3, and that will remove the borders of the button:



But flat is not simply about removing the borders of the button.  If you look at the trend these days, there are round buttons, etc.  To make this easy, I added as mentioned two new parameters to help give that look, nShpBackColor and nShpCurvature

nShpBackColor = is the color of the new shape for the flat look.
nShpCurvature = is the curvature of that shape, default is 90.  This gives you the ability to make it round, not too much, etc.

On default curvature of 90


Change curvature, your choice.  Here is how it looks with 15 value


In addition to the above, there are 3 colors it does when it is on flatlook appearance:

a.  The color you set for the shape
b.  The color for disabled buttonX which is somewhat of lighter shade than the color you set
c.  Hover color, lighter shade that is slightly different than the disabled color

Mini-X

There is this 3rd additional parameter I have also added here called LWithX.  By default, it is set to .F..  When you turn this into .T., then when a buttonX gets disabled, aside from the effect on the caption and color, it will have a small round red X on the left topmost corner of the button like this:



Flat-look on TitleBarX

If you are not aware of what  TitleBarX is, then take a look at this link http://sandstorm36.blogspot.com/2015/01/titlebarx-class.html .

Now, assuming you already knew about that class which is among those I shared that is part of ssUltimate library, ButtonX can now work on that easy (only on theme 0).  That as you change the color of your objects in your form, ButtonX can now follow with a shade of your choice.

To make it work better with TitleBarX, then instead of setting up the button inside the class itself, you can do that inside TitleBarX' _SwapColor Method like this:

DoDefault()
Thisform.BackColor = This._shade(-.20)
Local lnWhite, lnShade1
lnShade1 = This._shade(-.35)
lnWhite = Rgb(255,255,255)
With Thisform.PageFrame1.Page1
      .BackColor = This._shade(-.18)
      .contSearch.BackColor = This._shade(-.42)
      .cmdAdd._settings('\<Add',0,6,'new1.bmp',2,'Create a new borrower',.T.,,,13,m.lnWhite,,,3,m.lnShade1)
      .cmdEdit._settings('\<Edit',0,6,'openx.bmp',2,'Edit details of an existing borrower!',.T.,,,13,m.lnWhite,,,3,m.lnShade1)
ENDWITH





The last one showing the red X marker when the buttons are toggled as Disabled.  So when you use this last parameter, when you toggle the buttons, aside from the colors, you can easily spot the disabled one via that red X.

I will update soon my subscribers with ssUltimate after I finished posting guides on the latest inside the library.  One is about the new ConX class, the latest class I made to work with TitleBarX as well.  This ConX class can work as a container, a button, and a pageframe tab, your choice.



This also works hand-in-hand with TitleBarX giving you a flat look interface.


Dang, the colors on my laptop is really different than the external LCD, LOL!  Anyway, that is one point of ssUltimate especially the recent classes I made.  To give users the capability to choose whatever color that suits their eyes, individually, anytime.  And considering that every screen have different color balancing, then that fixes also the color difference that looks good on one but not on others.

Needless to say, depending on your taste, xButton can give you cool looking embossed buttons or  flat with curvature of your choice.

So what is ssUltimate Library?  Well all I can say is this library will give your app something that is not looking like a standard VFP app.  When I first created my very first library _sandstorm36, my plan is to terraform VFP Forms.  :)

by Jun Tangunan (noreply@blogger.com) at March 26, 2015 01:15 AM

March 25, 2015

Alex Feldstein

March 24, 2015

Rick Strahl's Web Log

Updated DeleteFiles Utility now on Chocolatey

Last year I posted about a small DeleteFiles utility I created that once and for all solved my problem of recursively deleting files and folders down a Windows folder hierarchy from the command line. On my server I constantly need to delete backup database and log files and other temporary file junk that piles up as part of 20 odd Web sites running their thing. On my local machine today I frequently need to clean out development package management folders for NPM or NuGet with specific folder specs. On my server I have scheduled tasks that fire batch files running DeleteFiles to clean out temp folders and backup folders. So for me deleting files based on a file spec is a common occurrence and DeleteFiles has been a really handy tool to make this easy with a simple single file executable.

Features

On the previous post there were a number of comments on how to accomplish this sort of thing just with the Windows command prompt using various helper tools or some goobledygook Powershell, but for me personally I prefer a simple solution that has a clearly defined purpose and syntax that is easily remembered without going on a pony hunt every time I need this facility.

So for this reason DeleteFiles has the following simple and focused feature set:

  • Delete files with simple file specs like  c:\temp\*.* or *.tmp
  • Recursively delete files down the folder hierarchy (-r switch)
  • Optionally delete empty folders (-f switch)
  • Filter files to delete based on days or seconds before current time (-d -s)
  • Files can be optionally dumped into the Recycle Bin for recoverable deletes (-y)
  • Preview mode lets you test run to see what would get deleted (-l)
  • Works with deeply nested folder hierarchies (like NPM folders)
  • Works around Windows MAX_PATH limitations
  • Portable, single-file EXE file

Get it

You can grab the executable either from Chocolatey or from GitHub along with the source code:

What’s New

Since the original version came out there have been a few additional features that have been added.

Long File Paths – greater than MAX_PATH

I’ve been working a lot with JavaScript projects lately and as a result have been using NPM. If you’ve done the same you’ve probably more than once have run into the problem of deep folder nesting where the folders nest so deep that Windows natively can’t access or delete the files and folders (folder nesting too deep). Basically the default Windows APIs have a path length limitation (MAX_PATH or 256 chars) that when exceeded makes the standard Windows tools like Explorer (and most Explorer replacements) as well as the standard del command on the command line fail.

Windows does allow for a workaround by using special path syntax (\\?\D:\very long path.) but you can’t use that easily in Explorer or the command line and the .NET BCL components also don’t actually support that natively .

I ended up adding support for greater MAX_PATH lengths by integrating the excellent ZetaLongPaths library and that’s a big improvement. In the process also a couple of other issues dealing with file locking have and read-only files have been addressed.

DeleteFiles can now be installed via Chocolatey

It took a while to get the package approved (growing pains at Chocolatey I suppose), but you can easily get DeleteFiles installed via the Chocolatey NuGet package. If you don’t know what Chocolatey is, do yourself a favor and head over to their site and install it immediately. Chocolatey is a NuGet like package manager for Windows that allows you easily discover and install many Windows Utilities and Applications quickly and without running installers explicitly. You can combine and automate installs easily in batch files and keep all of your utilities up to do data. These days for new machine installs I install 90% of all apps I use via Chocolatey. Yummy!

Quiet Mode

There’s now also a quiet mode that allows you to control the detail of messages that get spewed out. By default all files to be deleted are shown, but you can quiet that down to just a summary or no output at all other than the running banner.

Better safe than sorry: Preview Mode and Recycle Bin

You can now do a what-if run of your delete operations that shows you exactly what’s going to be deleted without actually deleting it. By default DeleteFiles hard deletes files but you can also use the –y option to delete files/folders to the recycle bin just in case you screw up by accident.

Try it out

This utility is very small and self contained in a single exe and has a very narrow use case, but to me it’s become something I use all the time. I have it in my global path (via Chocolatey’s install) so it’s easy to get to it quickly. I may not need it often but when I do it’s quick and easy to find and use with a simple command line interface that I can remember. Maybe you find it useful as well.

© Rick Strahl, West Wind Technologies, 2005-2015
Posted in Windows  

by Rick Strahl at March 24, 2015 10:49 PM

VisualFoxProWiki

MostValuableProfessional

Beginning January 2011, Microsoft will no longer be awarding MVP status in the Visual FoxPro expertise.

March 24, 2015 02:59 PM

Win32ApiShellNotifyIcon

Question: Is there an API call to add an icon to the systray? -- BarryDempsey

Yes (Shell_NotifyIcon in Shel32.Dll). Check Q149276 (HOWTO: Use Icons with the Windows 95/Windows 98 System Tray) (and article Q162613 HOWTO: Manipulate Icons in the System Tray with Visual Basic) in MSDN Libray. If you like the windows API take a look at Politically Correct File Operations also in MSDN (SHFile OperationOffsite link to http://www.news2news.com/vfp/?function=494 ), but unfortunatelly it requires a structure as parameter. -- Fernando Alvares

March 24, 2015 02:14 PM

Alex Feldstein

FoxProWiki

MostValuableProfessional

Editor comments: Mike Beane, now deceased.

March 24, 2015 12:23 AM

March 23, 2015

Alex Feldstein

Photo of the Day


Giant Swallowtail (Papilio cresphontes)
Fairchild Tropical Gardens

by Alex Feldstein (noreply@blogger.com) at March 23, 2015 05:00 AM

March 22, 2015

VisualFoxProWiki

MikeBeane

According to a Facebook post from his daughter, Mike passed away on March 19, 2015.


Software developer in Chicago -- FoxPro, Delphi, VB, SQL Server.

Contact Information:

email: mbeane@home.com
michael.beane@nsamedia.com
mbeane@compuserve.com

March 22, 2015 10:46 PM

Rahul Desai's Blog

Download Microsoft System Center Management Pack for Dynamics CRM 2015

 

By managing these Microsoft Dynamics CRM components in System Center Operations Manager, the administrator can respond quickly to critical events and key performance indicators, and take action to prevent service outages, reduce the resolution time for alert conditions, and increase the overall availability and performance of the Microsoft Dynamics CRM system.
Feature Summary

  • Monitors the availability and heath of the following components
    • Microsoft Dynamics CRM Server 2015
    • Microsoft Dynamics CRM 2015 E-mail Router
    • Microsoft Dynamics CRM 2015 Reporting Extensions
  • Monitors the availability and health of the following component services:
    • Microsoft Dynamics CRM Asynchronous Processing Service
    • Microsoft Dynamics CRM Asynchronous Processing Service (maintenance)
    • Microsoft Dynamics CRM Sandbox Processing Service
    • Microsoft Dynamics CRM E-mail Router Service
    • Microsoft Dynamics CRM Unzip Service
    • World Wide Web Publishing Service
    • Indexing Service
  • Monitors the availability and health of the following application components and functionality:
    • Operability of ISV plug-ins
    • Web application requests processing, SOAP exceptions, and unexpected failures
  • Monitors the performance metrics of the following components:
    • Web application requests processing
    • Database query processing
  • Monitors the system for configuration-related failures.

Download Microsoft System Center Management Pack for Dynamics CRM 2015 from Official Microsoft Download Center

by Rahul Desai at March 22, 2015 07:58 PM

Alex Feldstein

March 21, 2015

Alex Feldstein

Photo of the Day


Sara Longwing (Heliconius sara)
Fairchild Tropical Gardens

by Alex Feldstein (noreply@blogger.com) at March 21, 2015 05:00 AM

March 20, 2015

CULLY Technologies, LLC

ImageMagick Mogrify – Scale and Canvas Size

I was working on a slideshow project where I had about 200 images to manipulate. It’s easier to create the slideshow if the image size are similar with a consistent orientation, which basically means landscape images. For the portrait images, I was wanting to increase the canvas size to make the images effectively landscape. Remember that Linux is case sensitive so perform the operations on both *.jpg and *.JPG.

First, let’s size the images to a maximum dimention of 1600 pixels wide by 1200 pixels high. Size the images up and scale them down.
mogrify -resize 1600x1200 *.jpg

Second, let’s let the canvas grow so all images are now 1600 by 1200. The setting of the background color didn’t work for me. The default is white but I couldn’t get it to be black. Perhaps that will be fixed sometime.
mogrify -extent 1600x1200 -gravity Center *.jpg

I hope this helps someone out in the future. It will probably be me. You’re welcome, future me!

by kcully at March 20, 2015 05:47 PM

Alex Feldstein

March 19, 2015

Beth Massi - Sharing the goodness

The .NET Voyage into Open Source–dotnetConf 2015

dotnetConf is on now! Yesterday on Day 1, there were a ton of great presentations from the team. One of my personal favorites of the day was the talk where Immo, Rich and Miguel spoke about .NET Core and the teams journey into Open Source. There’s a lot of great insight into how culturally and technically we are going about it and the relationship between the .NET and Mono projects.

Check it out:

The .NET Voyage into Open Source

image

If you missed Day 1, you can watch them all on demand here: http://channel9.msdn.com/Events/dotnetConf/2015

Here’s some more of my other favorites.

.NET Core Deep Dive

Introduction to ASP.NET5

.NET Compiler Platform ("Roslyn"): Analyzers and the Rise of Code-Aware Libraries

Today is Day 2 and there are a ton of presentations being delivered by experts in our community today. Head to http://channel9.msdn.com to watch them now and later on demand.

I’m learning a ton! Enjoy!

by Beth Massi - Microsoft at March 19, 2015 04:54 PM

FoxProWiki

VFP9RuntimeFiles

Editor comments: New URL of wOOdy's archive
A minimal set of DLL's for VFP9 application
DLL Name Register (order) Default Location Other Locations Comment
msvcr71.dll No (1) App Folder Microsoft Shared\VFP, WinSysDir VC++ 7.1 Runtime library
gdiplus.dll No (1) Microsoft Shared\VFP App Folder, WinSysDir GDI+ support
vfp9r.dll Yes (2) --"-- --"-- STDLL and EXE support
vfp9t.dll Yes (2) --"-- --"-- MTDLL support
The runtimes for the language(s) you support:
vfp9renu.dll No The same as vfp9r.dll The same as vfp9r.dll English
vfp9resn.dll --"-- --"-- --"-- Spanish
vfp9rdeu.dll --"-- --"-- --"-- German
vfp9rfra.dll --"-- --"-- --"-- French
vfp9rrus.dll --"-- --"-- --"-- Russian
vfp9rcsy.dll --"-- --"-- --"-- Czech
vfp9rkor.dll --"-- --"-- --"-- Korean
vfp9rchs.dll --"-- --"-- --"-- Chinese (PRC)
vfp9rcht.dll --"-- --"-- --"-- Chinese (Taiwan)
To provide compressed HTML help (CHM) within your apps:
foxhhelp9.exe Yes
Microsoft Shared\VFP WinSysDir foxhhelp9.exe /regserver
foxhhelpps9.dll No --"-- --"--
XMLTOCURSOR() function requires MSXML 3 :
msxml3.dll Yes WinSysDir WinSysDir
msxml3r.dll No --"-- --"-- Required by msxml3.dll
msxml3a.dll --"-- --"-- --"-- --"--
XMLAdapter class and HTML/XML Report output requires MSXML 4 :
msxml4.dll Yes WinSysDir WinSysDir
msxml4r.dll No --"-- --"-- Required by msxml4.dll
Object-assisted Reporting :
REPORTBUILDER.APP No App Folder App Folder Report Writer
REPORTPREVIEW.APP --"-- --"-- --"-- Report Preview
REPORTOUTPUT.APP --"-- --"-- --"-- Report Output

March 19, 2015 04:24 PM

CarlKarsten

Carl Karsten
carl@personnelware.com To be sure your message gets past my spam blocker and delivered to me, add yourself to my whitelist: http://www.personnelware.com/hands/AddToList.html which I wrote in Python. But now onto my VFP doings...


info@chicagomidwestwineshow.com

I've specialized in payroll system development for 10 years. In particular I maintain a FPD2.6 payroll and billing system for temporary employment agencies.
I had been working primarily with FoxPro DOS and using VFP for small secondary projects. Aug 97 - Aug 99 I converted a client from my accounting system to People Soft. Having lost my largest FoxPro Dos client, I shifted my primary focus to VFP. Dec 99 I passed both VFP exams 70-155 and 156 which gives me MC P status.

I am an active member of Chicago FUDG, the local VFP user group.

I use F1's Visual FoxExpress as my prefered framework.
Resume: http://www.personnelware.com/carl/carlresume07.html
Payroll app site: http://www.personnelware.com
page of links I like: http://dev.personnelware.com/carl/cbp.html

I throw a lot of things on my local webserver; it is on a cable modem that uses DHCP, so the address changes every year. If you find these links not working, let me know so I can update the DNS. The good stuf can be found at http://dev.personnelware.com/carl

VFE tweeks can be found at: http://dev.personnelware.com/carl/vfe/tweeks/
bag of FRX tricks - http://www.personnelware.com/carl/vfp/foxtoy/foxtoy.html

March 19, 2015 11:41 AM

Alex Feldstein

March 18, 2015

Alex Feldstein

March 17, 2015

FoxProWiki

ToolsDevelopersUseAndLove

This is an index of tools coders couldn't live without.

Developers collect and use tools that solve productivity bottle necks regardless of the programming language they use. And any of use who use several languages would like to know about either cross-platform tools, or tools that serve a need that may only be in our periphery at the moment.

Are there more and more actually _useful_ tools? It might be that the profession is maturing to the point where new generations of programmers just expect to have productivity tools, instead of thinking it's not real programming unless they code every scrap themselves (whatever that means). Or, it might be that I'm just paying attention. So, feel free to add your two cents. I'll just start a list of ones I've heard of recently. If you use a tool, please flesh out the topic.

March 17, 2015 03:42 PM

Rick Strahl's Web Log

ASP.NET MVC, Localization and Westwind.Globalization for Db Resources

I’ve been hard at work with version 2.0 of the Westwind.Globalization library, which is a major update from version 1.x in terms of database support and general features, as well as a brand new much more user friendly (IMHO) Web resource editing interface. As a result I’m going to be posting a few related blog entries in the next couple of weeks.

Westwind.Globalization is a library to provide database driven resources in .NET using Sql Server, MySql, SqLite and SQLCe (for now) for providers. It implements standard resource providers and resource managers  and as such it can be used as a drop in replacement for Resx resources. There’s a ton of additional functionality including serving resources to JavaScript client applications, to importing and exporting Resx resources, generating strongly typed classes and of course the interactive Web Resource editor that makes it easy to edit resources interactively.

Westwind.Globalization and MVC

The focus of this post is to discuss ASP.NET MVC support of Westwind.Globalization. I’ve seen a number of questions and discussions that show confusion over whether Westwind.Globalization supports MVC properly. The short answer is – it does support MVC in every way. For the long answer read on. In this post I’ll give a short overview of how localization in MVC works in general, and then show how you can easily use Westwind.Globalization with MVC for those same scenarios.

Version 2.0 (in late beta now) in particular focuses on the MVC and also SPA scenarios (which I’ll leave for another post soon) and the new documentation that’s on GitHub along with the rest of the project now is much more generic and provides examples for both MVC (and non-Web projects as well) as well as WebForms.

Before we look at Westwind.Globalization let’s quickly review how localization – and specifically text resource localization – works in ASP.NET MVC in general.

Strongly Typed Resources and MVC

ASP.NET MVC unlike WebForms takes a much simpler approach to localization, relying mostly on strongly typed resources to localize content. MVC uses resources much more like all other project types in .NET, rather than the custom ResourceProvider model that ASP.NET has traditionally used.

MVC applications instead rely on strongly typed resources which in turn are tightly coupled wrapper classes around the Resx ResourceManager. The generated strongly typed resource classes are hardcoded to the standard .NET ResourceManager that uses Resx and there’s no easy way – short of generating the classes differently – to swap out and use a different ResourceManager. Westwind.Globalization provides a custom strongly typed resource generation mechanism via the Resource Editor Tool or via code based classes you can call and it essentially creates classes similar to the Resx generated ones but uses database (as well as Resx) resources.

Strongly typed resources work via static classes that attach to a static ResourceManager instance property. This resource manager is associated with a given ResourceSet which is a series of .Resx files with the same base name: ie. Resource.resx, Resources.resx.de, Resources.resx.fr. A given resource manager caches all its loaded ResourceSets internally in memory after a resource is accessed for the first time in a given resource set. This is an important point for all resource related tasks in .NET – resource sources tend to be accessed only once for each ResourceSet/Locale – after that all the resources are cached in memory for very fast subsequent loading. This also means that database resources use the database only initially before also using those same caching mechanisms that Resx resources enjoy.

Using Strongly Typed Resources in MVC

For MVC Views you can simply embed strongly typed resource properties as values into Razor views:

@using Westwind.Globalization.Sample.Properties
…
<button id="btnAdd" title="@Resources.Add_Title">@Resources.Add</button>

There’s nothing tricky about this and IMHO it’s a great simplification over the morass of features that existed in WebForms. WebForms had global resources, local resources, a Meta resources provider and resource expressions all using some obscure interfaces that could often fail horribly if resources weren’t available. MVC’s usage of plain Resx resources and strongly typed resources makes this process much easier even if it is tightly coupled to Resx resources and – it’s type safe so the compiler can help you find missing resource errors to boot.

In case you’re new to localization in .NET, standard .Resx localization works with Resx files that are essentially XML text files that contain resources as key value pairs. Resources values often are text, but they can also be images or other binary content. One or more .Resx files comprise a ResourceSet with an individual version for each localeId that you have localized for. So a typical .Resx setup looks like this:

ResxMVC

Each ‘ResourceSet’ is a group of .Resx files, one for each locale ID you localize for. The Resx files are essentially XML files that contain the localized resource content. You have a base .resx file which is considered the Invariant locale (the one without an explicit locale extension) and typically that one will contain the primary language – English for me. Then you have additional resx files with the same name but a different locale extension to provide the localized versions of the resources. Above there’s only LocalizationForm.de.resx but if you had additional locales to localize for you would add additional resource files for each of those locales. Locales can be top level locales like de, fr, en or culture specific versions such as en-US, de-DE, de-CH. ResourceManagers can retrieve resources using Resource Fallback which allows for resources to fall back to the next less specific region that has a value. So if you ask for a resources in en-US but you don’t have en-US or en resources, it’ll fall back to invariant: en-US->en->Invariant.

The designers show one resourceset for a specific locale id. When you open the designer for specific resource file you see the resources for that specific locale (Invariant/English in my case):

ResourceEditor

At the top of the designer there’s the Access Modifier dialog that allows you to specify if and how strongly typed resources are generated. Set to Public or Internal generates a class with the specified project visibility. The class then maps each of the resource keys in the invariant .resx file to properties of a class:

public class LocalizationForm { private static global::System.Resources.ResourceManager resourceMan; private static global::System.Globalization.CultureInfo resourceCulture; [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal LocalizationForm() { } /// <summary> /// Returns the cached ResourceManager instance used by this class. /// </summary> [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] public static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Westwind.Globalization.Sample.LocalizationAdmin.Properties.LocalizationForm", typeof(LocalizationForm).Assembly); resourceMan = temp; } return resourceMan; } } /// <summary> /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// </summary> [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] public static global::System.Globalization.CultureInfo Culture { get { return resourceCulture; } set { resourceCulture = value; } } /// <summary> /// Looks up a localized string similar to Add. /// </summary> public static string Add { get { return ResourceManager.GetString("Add", resourceCulture); } } /// <summary> /// Looks up a localized string similar to Add a new individual resource.. /// </summary> public static string Add_Title { get { return ResourceManager.GetString("Add.Title", resourceCulture); } }

}

Essentially this code creates a static ResourceManager instance that holds a dictionary of resource sets for each of the supported locales which are loaded when you access the first resource. The resource manager loads each used resource set, and then performs a look up with resource fallback if an exact match can’t be found to return the resource in question.

You can then use these resources in your Razor views or inside of code as simple type names.

In Razor:

@using Westwind.Globalization.Sample.Properties
…
<button id="btnAdd" title="@Resources.Add_Title">@Resources.Add</button>

Inside of Controller or other MVC application code you can simply access the resource:

string text = string.Format("{0} - {1}", Resources.Add_Title, Resources.Title);

Easy enough, right? It works the same resources have always worked in library or console applications. There’s no special mechanism to bind resource names or designers to step in between because MVC’s UI is simply text and the strongly typed resources work very well for that.

Model Validation

Model Validation to show error information is a big feature in ASP.NET MVC and localizing the validation messages is a just as  important. The process of localizing these validation messages is a bit ugly, but due to the attribute based nature of validation which doesn’t directly allow for assigning dynamic values at runtime –  the ugliness is a necessary side effect.

Model Validation with resources looks like this:

public class ViewModelWithLocalizedAttributes
{
    [Required(ErrorMessageResourceName = "NameIsRequired", ErrorMessageResourceType = typeof(Resources))]
    public string Name { get; set; }

    [Required(ErrorMessageResourceName = "AddressIsRequired", ErrorMessageResourceType = typeof(Resources))]
    public string Address { get; set; }
}

The key here are the Attribute parameters ErrorMessageResourceName and ErrorMessageResourceType which point at a resource type and property name respectively. The first attribute effectively points at the Resources.NameIsRequired property of my  strongly typed resource class. As you can see for this to work you have to have strongly typed resources in place. Behind the scenes MVC uses Reflection to call GetProperty() on the provided type to retrieve the localized value via the ResourceManager.

Setting Resource Culture

One of the key aspects of localization is to detect the browser’s locale and then setting the applications Culture and UICulture to match the browser’s settings. ASP.NET provides some basic features for this using a configuration value in web.config and the system.Web section:

 <globalization uiCulture="auto:en-US" culture="auto:en-US" />

This automatically sniffs the client browsers locale (if available) and sets ASP.NET request thread’s Culture and UICulture to that locale. If the client doesn’t provide a Accept-Language header, the application falls back to en-US as the default locale I’ve specified after the colon.

Advertisement

This works fairly well in some scenarios, but usually this is not what you actually want – more typically your applications are localized only for a few specific locales. Very few applications on Western servers are likely to be localized for Mongolian or Zulu. Rather you typically want your application to switch to only a few locales that your application is actually localized for.

I wrote about how to do this before but with the Westwind.Web NuGet package and the WebUtils class (also part of the Westwind.Globalization package) you can simply do:

WebUtils.SetUserLocale(currencySymbol: "$",allowedLocales: "en,de,fr");

This limits the locale switching to en,de,fr – all others fall back to the server’s default locale which in my case is en-US. This way I can localize for the languages I support, but for everything else that’s not supported it falls back to the default of English.

Westwind.Globalization – Database Resources

Ok so now we know how MVC works with localization, lets look at Westwind.Globalization and MVC support.

Database driven resources are a powerful thing in that let you more easily manage your resources. Rather than the limited Resource editor in Visual Studio you can create a more flexible resource editor interface or update resources programmatically. To me personally, I like the fact that I can dynamically edit resources in a live application and see the change immediately. I also like the fact that I can create custom views where I can see all the resources associated with a given ResourceID at a glance and then edit and use localization tools to translate the text in one place.

Westwind.Globalization comes with this online resource editor that makes it very quick to edit and enter resources manually:

or you can use translation services to provide at least some rudimentary translation that you can modify or adjust:

Resources can be imported or manually created. The Resx import can pull in existing resources from a project. The ResourceProviders and ResourceManagers in Westwind.Globalization can then expose the database resources in the same way you use .Resx resources today, as well as providing strongly typed resources or exporting resources back out to Resx resources if you rather run production apps with Resx instead of dynamic database resources.

Westwind.Globalization and MVC

The original version of Westwind.Globalization was built for WebForms because that’s what the prominent platform was at the time. However, the library and related tooling has always supported ASP.NET MVC features all along – it just wasn’t quite as obvious as the WebForms features. In Version 2 a lot more focus is on the core features and thus the MVC support is featured more prominently and the documentation has been completely rewritten.

Westwind.Globalization works by implementing custom ASP.NET ResourceProviders (2 different ones) as well as a standard .NET ResourceManager that can pull resources out of a database. Both the providers and resource manager use a custom data layer to pull resources out of a database instead of from Resx resources. The data-layer provides for the basic ResourceSet loading as well as more sophisticated support for loading, updating and generally managing resources of resources including generation of strong classes, Resx and JavaScript exports etc. across all supported providers.

Because the library relies on standard .NET resource interfaces, to expose the actual resources, the ResourceProviders and ResourceManager cache ResourceSets after initially getting loaded on first access. The database gets hit only once per resource set for the lifetime of an AppDomain, so if I have 2 resourceSets with two localized languages the database effectively gets hit a max of 4 times. Not every resource access fires through the database as resources are cached in the standard .NET ResourceSet resource dictionaries. For this reason there is also support for local data engines like SQLite and SqlCompact, because resource management and access has very low impact on the database while providing the ability to dynamically edited resources in real time.

Westwind.Globalization offers a number of different ways to expose databased resources.

DbRes – Explicit Resource Loading

The static DbRes class is a very simple resource implementation that lets you easily translate resources based on string based values. This is similar to ResourceManager.GetObject() or GetString(), but with a twist that it will return the resource Id value you passed in. What this allows you to do is use a string based localization where default values are always available. This implementation uses ResourceManagers and writes out resources to disk:

// Using current UiCulture – empty resource set name
DbRes.T("HelloWorld");

// Exact match with resource - Hallo Welt
DbRes.T("HelloWorld", "Resources", "de");

// Resource Fallback to de if de-CH doesn't exist - Hallo Welt
DbRes.T("HelloWorld", "Resources", "de-CH");

DbRes.T() returns the matching resource value for the specified locale or the default locale the application is currently running in. You can explicitly override the locale. If a resourceId cannot be found the resource ID value is returned – so you always get something back, never empty resources.

You can also easily use DbRes in Razor markup:

@DbRes.T("HelloWorld", "Resources")

This is a real easy way to use Db generated resources without any further setup or configuration.

This was a feature a number of developers have requested as they didn’t want to have to explicitly pre-create resources in a resource editor and didn’t want to have to deal with exporting resources to strongly typed resources constantly. Rather – combined with Westwind.Globalization’s AddMissingResources option – you could simply embed resource expressions into the page and the resource keys are then automatically generated for later editing (or simply leaving them as is).

Further some people prefer using the Resource ID as the actual default text. Resource IDs don’t have to be ‘ids’ but can be any string and so you can easily have a resource key like “Hello World” which then provides the default ‘key’. The idea is that you can use these text based resource Ids to provide the default locale value that ensures that at least the default text will always show up rather than a resource key. It’s not for every application but I’ve heard this request over and over again, and I’ve been involved in several projects that use this approach to great effect. It’s especially appealing to those applications that used in the ‘make it localization ready camp’ where the actual translation to other languages doesn’t occur until much later (or maybe never at all). Using this approach the resources get into the project and the database fairly transparently.

Strongly Typed Resources

As mentioned at the beginning of this post ASP.NET MVC internally is more or less designed around strongly typed resources. You can also generate strongly typed resources from database resources with Westwind.Globalization. This can be handled through the Web Administration interface of the tooling or via a class that can automate the process.

CreateClasses

ResourceExport2

Clicking the Create Classes button generates a set of strongly typed classes for each of the resource sets maintained in the database. The class handles several different ways of returning resources using either DbResourceManager, or using the configured ASP.NET ResourceProvider or using plain .NET Resx resources. The latter is useful if you decide to later export your database resources to Resx – a simple switch in the generated source file via a static property can switch between any of these operational modes.

Here’s what this generated file looks like:

public class GeneratedResourceSettings
{
    // You can change the ResourceAccess Mode globally in Application_Start        
    public static ResourceAccessMode ResourceAccessMode = ResourceAccessMode.AspNetResourceProvider;
}

public class Resources { public static ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { var temp = new ResourceManager("Westwind.Globalization.Sample.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; } } private static ResourceManager resourceMan = null; public static System.String Add { get { if (GeneratedResourceSettings.ResourceAccessMode == ResourceAccessMode.AspNetResourceProvider) return (System.String) HttpContext.GetGlobalResourceObject("Resources","Add"); if (GeneratedResourceSettings.ResourceAccessMode == ResourceAccessMode.Resx) return ResourceManager.GetString("Add"); return DbRes.T("Add","Resources"); } } public static System.String Add_Title { get { if (GeneratedResourceSettings.ResourceAccessMode == ResourceAccessMode.AspNetResourceProvider) return (System.String) HttpContext.GetGlobalResourceObject("Resources","Add_Title"); if (GeneratedResourceSettings.ResourceAccessMode == ResourceAccessMode.Resx) return ResourceManager.GetString("Add_Title"); return DbRes.T("Add_Title","Resources"); } } public static System.String NameIsRequired { get { if (GeneratedResourceSettings.ResourceAccessMode == ResourceAccessMode.AspNetResourceProvider) return (System.String) HttpContext.GetGlobalResourceObject("Resources","NameIsRequired"); if (GeneratedResourceSettings.ResourceAccessMode == ResourceAccessMode.Resx) return ResourceManager.GetString("NameIsRequired"); return DbRes.T("NameIsRequired","Resources"); } } public static System.String HelloWorld { get { if (GeneratedResourceSettings.ResourceAccessMode == ResourceAccessMode.AspNetResourceProvider) return (System.String) HttpContext.GetGlobalResourceObject("Resources","HelloWorld"); if (GeneratedResourceSettings.ResourceAccessMode == ResourceAccessMode.Resx) return ResourceManager.GetString("HelloWorld"); return DbRes.T("HelloWorld","Resources"); } } public static System.String AddressIsRequired { get { if (GeneratedResourceSettings.ResourceAccessMode == ResourceAccessMode.AspNetResourceProvider) return (System.String) HttpContext.GetGlobalResourceObject("Resources","AddressIsRequired"); if (GeneratedResourceSettings.ResourceAccessMode == ResourceAccessMode.Resx) return ResourceManager.GetString("AddressIsRequired"); return DbRes.T("AddressIsRequired","Resources"); } } }

Unlike string resources using DbRes, strongly typed resources require that you recompile your application after the classes have been generated. The process of generation of the strongly typed classes is not automatic so whenever you add resources in the resource editor you have to explicitly regenerate – unless you create some build drive code that can automatically perform this task which can be accomplished with a couple of lines of code.

Once generated, you can then use the generated strongly typed resource classes in the same way you would use strongly typed resources in any other ASP.NET MVC or other project.

So this still works just as it did before:

@using Westwind.Globalization.Sample.LocalizationAdmin.Properties
…
<button id="btnAdd" title="@Resources.Add_Title">@Resources.Add</button>

as does:

string text = string.Format("{0} - {1}", Resources.Add_Title, Resources.Title);

IOW, exactly the same way as you could before with Resx resources.

Likewise MVC Model Validation also works off these strongly typed classes in the same way as before:

public class ViewModelWithLocalizedAttributes
{
    [Required(ErrorMessageResourceName = "NameIsRequired", ErrorMessageResourceType = typeof(Resources))]
    public string Name { get; set; }

    [Required(ErrorMessageResourceName = "AddressIsRequired", ErrorMessageResourceType = typeof(Resources))]
    public string Address { get; set; }
}

As you can see you can pretty much do everything you can do with standard Resx resources using the database provider directly. If you still find scenarios where you can’t work with DbResources – maybe you have to pull resources from several different sources or you have to work with library projects – you also have the option to export resources back to Resx resources.

Exporting Database Resources to .Resx

The administration interface of Westwind.Globalization – as well as some of the support classes – allow you to import and export resources from and to .Resx. So if you find that after you’ve localized your application using database resources that you’d rather ship the application with fixed Resx resources that are guaranteed to always work regardless of whether a database is live or not – you can do that as well.

On the Web Resource Editor you can use the Import or Export Resx option. To export resources you can specify a base path to export to:

ExportResources

This creates individual .Resx files for each resource set and resource locale in the specified folder. There’s a project mode – Project here and what is appropriate for MVC or standard .NET projects that use Resx resources – or WebForms mode which creates Local and Global resources instead.

As you can see on the resource dialog you can actually use the resource editor to export resources to an arbitrary location on the local disk. This actually lets you export resources to non-Web projects and lets you use the Resource Editor as a general purpose resource editor, which is pretty cool…

Once the resources have been exported you won’t automatically have strongly typed resources. In order to get them you have two choices:

  • Manually set the Resource Generator on invariant .Resx file
  • Generate strongly typed resources from the db resources

Manually set the Visual Studio Resource Generator

The first option is to simply open each invariant .Resx file and set the resource generator to the appropriate Internal or Public class generator as shown earlier on the Resx editor form earlier. You can also do this at the Visual Studio Project file level and select all of the .Resx files, then set the Custom Tool in one go:

ResxGenerator

Recompile and you have your strongly typed resources. Once the .Resx files and strongly typed resource files exist, you can simply re-export when you have changes and those changes will update the Resx files. Recompiling will re-generate the strongly typed classes automatically so you’re good to go – it’s a one time configuration thing.

Note that it’s entirely possible to work with database resources for editing purposes only and then simply dump the resources out to Resx as you make changes for testing and deploying. You don’t actually have to run with db resources in a live environment using this approach. Live db resources are useful if you want to change resources in real time while the application is running and see the changes reflected immediately. Otherwise exporting to Resx files offers a good option that provides all the features you expect from resx features (portability as part of the compiled code, always available etc.).

Export Strongly Typed Classes from Web Db Resource Editor

The other option is to export Resx resources and then also generate the strongly typed classes from the Web Resource Editor interface as shown earlier. When the strongly typed classes have been exported you can specify that you want resources served from Resx files instead.

To make this work you’ll have to set one switch on application startup:

protected void Application_Start() {
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes);
GeneratedResourceSettings.ResourceAccessMode = ResourceAccessMode.Resx;

}

This directs the Property retrieval to look for resources in Resx files using the static resource manager. This works exactly the same as strongly typed Resx resources but you have a single step to generate this class and setting.

So now if you want to switch between db resources and resx resources you can simply comment/uncomment the above flag.

Summary

As you can see Westwind.Globalization can work great in ASP.NET MVC and there are many options of how you can work with resources using this tool. You can run entirely with Db resources, or you can choose to import .Resx resources, edit them and then run your production code with standard .Resx resources with just a couple of extra steps. You have lots of choices on how you can run your localized resources and the localization tasks with this library.

Version 2.0 brings a number of big improvements and is much more focused on the MVC scenario since that paradigm has pretty much taken over. WebForms users don’t need to fret though: All the WebForms specific features like ResourceProvider, Meta Resources and Resource expressions, designer  support etc. all continue to work.

Version 2.0 is in late beta and packages are available on NuGet, but since this is a beta make sure you allow Pre-Release packages to be loaded. The current release is beta 3 which released last night and I hope to get the final release out in the next couple of weeks at the latest.

Resources

© Rick Strahl, West Wind Technologies, 2005-2015

by Rick Strahl at March 17, 2015 02:53 PM

ASP.NET MVC, Localization and Westwind.Globalization for Db Resources

I’ve been hard at work with version 2.0 of the Westwind.Globalization library, which is a major update from version 1.x in terms of database support and general features, as well as a brand new much more user friendly (IMHO) Web resource editing interface. As a result I’m going to be posting a few related blog entries in the next couple of weeks.

Westwind.Globalization is a library to provide database driven resources in .NET using Sql Server, MySql, SqLite and SQLCe (for now) for providers. It implements standard resource providers and resource managers  and as such it can be used as a drop in replacement for Resx resources. There’s a ton of additional functionality including serving resources to JavaScript client applications, to importing and exporting Resx resources, generating strongly typed classes and of course the interactive Web Resource editor that makes it easy to edit resources interactively.

Westwind.Globalization and MVC

The focus of this post is to discuss ASP.NET MVC support of Westwind.Globalization. I’ve seen a number of questions and discussions that show confusion over whether Westwind.Globalization supports MVC properly. The short answer is – it does support MVC in every way. For the long answer read on. In this post I’ll give a short overview of how localization in MVC works in general, and then show how you can easily use Westwind.Globalization with MVC for those same scenarios.

Version 2.0 (in late beta now) in particular focuses on the MVC and also SPA scenarios (which I’ll leave for another post soon) and the new documentation that’s on GitHub along with the rest of the project now is much more generic and provides examples for both MVC (and non-Web projects as well) as well as WebForms.

Before we look at Westwind.Globalization let’s quickly review how localization – and specifically text resource localization – works in ASP.NET MVC in general.

Strongly Typed Resources and MVC

ASP.NET MVC unlike WebForms takes a much simpler approach to localization, relying mostly on strongly typed resources to localize content. MVC uses resources much more like all other project types in .NET, rather than the custom ResourceProvider model that ASP.NET has traditionally used.

MVC applications instead rely on strongly typed resources which in turn are tightly coupled wrapper classes around the Resx ResourceManager. The generated strongly typed resource classes are hardcoded to the standard .NET ResourceManager that uses Resx and there’s no easy way – short of generating the classes differently – to swap out and use a different ResourceManager. Westwind.Globalization provides a custom strongly typed resource generation mechanism via the Resource Editor Tool or via code based classes you can call and it essentially creates classes similar to the Resx generated ones but uses database (as well as Resx) resources.

Strongly typed resources work via static classes that attach to a static ResourceManager instance property. This resource manager is associated with a given ResourceSet which is a series of .Resx files with the same base name: ie. Resource.resx, Resources.resx.de, Resources.resx.fr. A given resource manager caches all its loaded ResourceSets internally in memory after a resource is accessed for the first time in a given resource set. This is an important point for all resource related tasks in .NET – resource sources tend to be accessed only once for each ResourceSet/Locale – after that all the resources are cached in memory for very fast subsequent loading. This also means that database resources use the database only initially before also using those same caching mechanisms that Resx resources enjoy.

Using Strongly Typed Resources in MVC

For MVC Views you can simply embed strongly typed resource properties as values into Razor views:

@using Westwind.Globalization.Sample.Properties
…
<button id="btnAdd" title="@Resources.Add_Title">@Resources.Add</button>

There’s nothing tricky about this and IMHO it’s a great simplification over the morass of features that existed in WebForms. WebForms had global resources, local resources, a Meta resources provider and resource expressions all using some obscure interfaces that could often fail horribly if resources weren’t available. MVC’s usage of plain Resx resources and strongly typed resources makes this process much easier even if it is tightly coupled to Resx resources and – it’s type safe so the compiler can help you find missing resource errors to boot.

In case you’re new to localization in .NET, standard .Resx localization works with Resx files that are essentially XML text files that contain resources as key value pairs. Resources values often are text, but they can also be images or other binary content. One or more .Resx files comprise a ResourceSet with an individual version for each localeId that you have localized for. So a typical .Resx setup looks like this:

ResxMVC

Each ‘ResourceSet’ is a group of .Resx files, one for each locale ID you localize for. The Resx files are essentially XML files that contain the localized resource content. You have a base .resx file which is considered the Invariant locale (the one without an explicit locale extension) and typically that one will contain the primary language – English for me. Then you have additional resx files with the same name but a different locale extension to provide the localized versions of the resources. Above there’s only LocalizationForm.de.resx but if you had additional locales to localize for you would add additional resource files for each of those locales. Locales can be top level locales like de, fr, en or culture specific versions such as en-US, de-DE, de-CH. ResourceManagers can retrieve resources using Resource Fallback which allows for resources to fall back to the next less specific region that has a value. So if you ask for a resources in en-US but you don’t have en-US or en resources, it’ll fall back to invariant: en-US->en->Invariant.

The designers show one resourceset for a specific locale id. When you open the designer for specific resource file you see the resources for that specific locale (Invariant/English in my case):

ResourceEditor

At the top of the designer there’s the Access Modifier dialog that allows you to specify if and how strongly typed resources are generated. Set to Public or Internal generates a class with the specified project visibility. The class then maps each of the resource keys in the invariant .resx file to properties of a class:

public class LocalizationForm { private static global::System.Resources.ResourceManager resourceMan; private static global::System.Globalization.CultureInfo resourceCulture; [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal LocalizationForm() { } /// <summary> /// Returns the cached ResourceManager instance used by this class. /// </summary> [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] public static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Westwind.Globalization.Sample.LocalizationAdmin.Properties.LocalizationForm", typeof(LocalizationForm).Assembly); resourceMan = temp; } return resourceMan; } } /// <summary> /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// </summary> [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] public static global::System.Globalization.CultureInfo Culture { get { return resourceCulture; } set { resourceCulture = value; } } /// <summary> /// Looks up a localized string similar to Add. /// </summary> public static string Add { get { return ResourceManager.GetString("Add", resourceCulture); } } /// <summary> /// Looks up a localized string similar to Add a new individual resource.. /// </summary> public static string Add_Title { get { return ResourceManager.GetString("Add.Title", resourceCulture); } }

}

Essentially this code creates a static ResourceManager instance that holds a dictionary of resource sets for each of the supported locales which are loaded when you access the first resource. The resource manager loads each used resource set, and then performs a look up with resource fallback if an exact match can’t be found to return the resource in question.

You can then use these resources in your Razor views or inside of code as simple type names.

In Razor:

@using Westwind.Globalization.Sample.Properties
…
<button id="btnAdd" title="@Resources.Add_Title">@Resources.Add</button>

Inside of Controller or other MVC application code you can simply access the resource:

string text = string.Format("{0} - {1}", Resources.Add_Title, Resources.Title);

Easy enough, right? It works the same resources have always worked in library or console applications. There’s no special mechanism to bind resource names or designers to step in between because MVC’s UI is simply text and the strongly typed resources work very well for that.

Model Validation

Model Validation to show error information is a big feature in ASP.NET MVC and localizing the validation messages is a just as  important. The process of localizing these validation messages is a bit ugly, but due to the attribute based nature of validation which doesn’t directly allow for assigning dynamic values at runtime –  the ugliness is a necessary side effect.

Model Validation with resources looks like this:

public class ViewModelWithLocalizedAttributes
{
    [Required(ErrorMessageResourceName = "NameIsRequired", ErrorMessageResourceType = typeof(Resources))]
    public string Name { get; set; }

    [Required(ErrorMessageResourceName = "AddressIsRequired", ErrorMessageResourceType = typeof(Resources))]
    public string Address { get; set; }
}

The key here are the Attribute parameters ErrorMessageResourceName and ErrorMessageResourceType which point at a resource type and property name respectively. The first attribute effectively points at the Resources.NameIsRequired property of my  strongly typed resource class. As you can see for this to work you have to have strongly typed resources in place. Behind the scenes MVC uses Reflection to call GetProperty() on the provided type to retrieve the localized value via the ResourceManager.

Setting Resource Culture

One of the key aspects of localization is to detect the browser’s locale and then setting the applications Culture and UICulture to match the browser’s settings. ASP.NET provides some basic features for this using a configuration value in web.config and the system.Web section:

 <globalization uiCulture="auto:en-US" culture="auto:en-US" />

This automatically sniffs the client browsers locale (if available) and sets ASP.NET request thread’s Culture and UICulture to that locale. If the client doesn’t provide a Accept-Language header, the application falls back to en-US as the default locale I’ve specified after the colon.

Advertisement

This works fairly well in some scenarios, but usually this is not what you actually want – more typically your applications are localized only for a few specific locales. Very few applications on Western servers are likely to be localized for Mongolian or Zulu. Rather you typically want your application to switch to only a few locales that your application is actually localized for.

I wrote about how to do this before but with the Westwind.Web NuGet package and the WebUtils class (also part of the Westwind.Globalization package) you can simply do:

WebUtils.SetUserLocale(currencySymbol: "$",allowedLocales: "en,de,fr");

This limits the locale switching to en,de,fr – all others fall back to the server’s default locale which in my case is en-US. This way I can localize for the languages I support, but for everything else that’s not supported it falls back to the default of English.

Westwind.Globalization – Database Resources

Ok so now we know how MVC works with localization, lets look at Westwind.Globalization and MVC support.

Database driven resources are a powerful thing in that let you more easily manage your resources. Rather than the limited Resource editor in Visual Studio you can create a more flexible resource editor interface or update resources programmatically. To me personally, I like the fact that I can dynamically edit resources in a live application and see the change immediately. I also like the fact that I can create custom views where I can see all the resources associated with a given ResourceID at a glance and then edit and use localization tools to translate the text in one place.

Westwind.Globalization comes with this online resource editor that makes it very quick to edit and enter resources manually:

or you can use translation services to provide at least some rudimentary translation that you can modify or adjust:

Resources can be imported or manually created. The Resx import can pull in existing resources from a project. The ResourceProviders and ResourceManagers in Westwind.Globalization can then expose the database resources in the same way you use .Resx resources today, as well as providing strongly typed resources or exporting resources back out to Resx resources if you rather run production apps with Resx instead of dynamic database resources.

Westwind.Globalization and MVC

The original version of Westwind.Globalization was built for WebForms because that’s what the prominent platform was at the time. However, the library and related tooling has always supported ASP.NET MVC features all along – it just wasn’t quite as obvious as the WebForms features. In Version 2 a lot more focus is on the core features and thus the MVC support is featured more prominently and the documentation has been completely rewritten.

Westwind.Globalization works by implementing custom ASP.NET ResourceProviders (2 different ones) as well as a standard .NET ResourceManager that can pull resources out of a database. Both the providers and resource manager use a custom data layer to pull resources out of a database instead of from Resx resources. The data-layer provides for the basic ResourceSet loading as well as more sophisticated support for loading, updating and generally managing resources of resources including generation of strong classes, Resx and JavaScript exports etc. across all supported providers.

Because the library relies on standard .NET resource interfaces, to expose the actual resources, the ResourceProviders and ResourceManager cache ResourceSets after initially getting loaded on first access. The database gets hit only once per resource set for the lifetime of an AppDomain, so if I have 2 resourceSets with two localized languages the database effectively gets hit a max of 4 times. Not every resource access fires through the database as resources are cached in the standard .NET ResourceSet resource dictionaries. For this reason there is also support for local data engines like SQLite and SqlCompact, because resource management and access has very low impact on the database while providing the ability to dynamically edited resources in real time.

Westwind.Globalization offers a number of different ways to expose databased resources.

DbRes – Explicit Resource Loading

The static DbRes class is a very simple resource implementation that lets you easily translate resources based on string based values. This is similar to ResourceManager.GetObject() or GetString(), but with a twist that it will return the resource Id value you passed in. What this allows you to do is use a string based localization where default values are always available. This implementation uses ResourceManagers and writes out resources to disk:

// Using current UiCulture – empty resource set name
DbRes.T("HelloWorld");

// Exact match with resource - Hallo Welt
DbRes.T("HelloWorld", "Resources", "de");

// Resource Fallback to de if de-CH doesn't exist - Hallo Welt
DbRes.T("HelloWorld", "Resources", "de-CH");

DbRes.T() returns the matching resource value for the specified locale or the default locale the application is currently running in. You can explicitly override the locale. If a resourceId cannot be found the resource ID value is returned – so you always get something back, never empty resources.

You can also easily use DbRes in Razor markup:

@DbRes.T("HelloWorld", "Resources")

This is a real easy way to use Db generated resources without any further setup or configuration.

This was a feature a number of developers have requested as they didn’t want to have to explicitly pre-create resources in a resource editor and didn’t want to have to deal with exporting resources to strongly typed resources constantly. Rather – combined with Westwind.Globalization’s AddMissingResources option – you could simply embed resource expressions into the page and the resource keys are then automatically generated for later editing (or simply leaving them as is).

Further some people prefer using the Resource ID as the actual default text. Resource IDs don’t have to be ‘ids’ but can be any string and so you can easily have a resource key like “Hello World” which then provides the default ‘key’. The idea is that you can use these text based resource Ids to provide the default locale value that ensures that at least the default text will always show up rather than a resource key. It’s not for every application but I’ve heard this request over and over again, and I’ve been involved in several projects that use this approach to great effect. It’s especially appealing to those applications that used in the ‘make it localization ready camp’ where the actual translation to other languages doesn’t occur until much later (or maybe never at all). Using this approach the resources get into the project and the database fairly transparently.

Strongly Typed Resources

As mentioned at the beginning of this post ASP.NET MVC internally is more or less designed around strongly typed resources. You can also generate strongly typed resources from database resources with Westwind.Globalization. This can be handled through the Web Administration interface of the tooling or via a class that can automate the process.

CreateClasses

ResourceExport2

Clicking the Create Classes button generates a set of strongly typed classes for each of the resource sets maintained in the database. The class handles several different ways of returning resources using either DbResourceManager, or using the configured ASP.NET ResourceProvider or using plain .NET Resx resources. The latter is useful if you decide to later export your database resources to Resx – a simple switch in the generated source file via a static property can switch between any of these operational modes.

Here’s what this generated file looks like:

public class GeneratedResourceSettings
{
    // You can change the ResourceAccess Mode globally in Application_Start        
    public static ResourceAccessMode ResourceAccessMode = ResourceAccessMode.AspNetResourceProvider;
}

public class Resources { public static ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { var temp = new ResourceManager("Westwind.Globalization.Sample.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; } } private static ResourceManager resourceMan = null; public static System.String Add { get { if (GeneratedResourceSettings.ResourceAccessMode == ResourceAccessMode.AspNetResourceProvider) return (System.String) HttpContext.GetGlobalResourceObject("Resources","Add"); if (GeneratedResourceSettings.ResourceAccessMode == ResourceAccessMode.Resx) return ResourceManager.GetString("Add"); return DbRes.T("Add","Resources"); } } public static System.String Add_Title { get { if (GeneratedResourceSettings.ResourceAccessMode == ResourceAccessMode.AspNetResourceProvider) return (System.String) HttpContext.GetGlobalResourceObject("Resources","Add_Title"); if (GeneratedResourceSettings.ResourceAccessMode == ResourceAccessMode.Resx) return ResourceManager.GetString("Add_Title"); return DbRes.T("Add_Title","Resources"); } } public static System.String NameIsRequired { get { if (GeneratedResourceSettings.ResourceAccessMode == ResourceAccessMode.AspNetResourceProvider) return (System.String) HttpContext.GetGlobalResourceObject("Resources","NameIsRequired"); if (GeneratedResourceSettings.ResourceAccessMode == ResourceAccessMode.Resx) return ResourceManager.GetString("NameIsRequired"); return DbRes.T("NameIsRequired","Resources"); } } public static System.String HelloWorld { get { if (GeneratedResourceSettings.ResourceAccessMode == ResourceAccessMode.AspNetResourceProvider) return (System.String) HttpContext.GetGlobalResourceObject("Resources","HelloWorld"); if (GeneratedResourceSettings.ResourceAccessMode == ResourceAccessMode.Resx) return ResourceManager.GetString("HelloWorld"); return DbRes.T("HelloWorld","Resources"); } } public static System.String AddressIsRequired { get { if (GeneratedResourceSettings.ResourceAccessMode == ResourceAccessMode.AspNetResourceProvider) return (System.String) HttpContext.GetGlobalResourceObject("Resources","AddressIsRequired"); if (GeneratedResourceSettings.ResourceAccessMode == ResourceAccessMode.Resx) return ResourceManager.GetString("AddressIsRequired"); return DbRes.T("AddressIsRequired","Resources"); } } }

Unlike string resources using DbRes, strongly typed resources require that you recompile your application after the classes have been generated. The process of generation of the strongly typed classes is not automatic so whenever you add resources in the resource editor you have to explicitly regenerate – unless you create some build drive code that can automatically perform this task which can be accomplished with a couple of lines of code.

Once generated, you can then use the generated strongly typed resource classes in the same way you would use strongly typed resources in any other ASP.NET MVC or other project.

So this still works just as it did before:

@using Westwind.Globalization.Sample.LocalizationAdmin.Properties
…
<button id="btnAdd" title="@Resources.Add_Title">@Resources.Add</button>

as does:

string text = string.Format("{0} - {1}", Resources.Add_Title, Resources.Title);

IOW, exactly the same way as you could before with Resx resources.

Likewise MVC Model Validation also works off these strongly typed classes in the same way as before:

public class ViewModelWithLocalizedAttributes
{
    [Required(ErrorMessageResourceName = "NameIsRequired", ErrorMessageResourceType = typeof(Resources))]
    public string Name { get; set; }

    [Required(ErrorMessageResourceName = "AddressIsRequired", ErrorMessageResourceType = typeof(Resources))]
    public string Address { get; set; }
}

As you can see you can pretty much do everything you can do with standard Resx resources using the database provider directly. If you still find scenarios where you can’t work with DbResources – maybe you have to pull resources from several different sources or you have to work with library projects – you also have the option to export resources back to Resx resources.

Exporting Database Resources to .Resx

The administration interface of Westwind.Globalization – as well as some of the support classes – allow you to import and export resources from and to .Resx. So if you find that after you’ve localized your application using database resources that you’d rather ship the application with fixed Resx resources that are guaranteed to always work regardless of whether a database is live or not – you can do that as well.

On the Web Resource Editor you can use the Import or Export Resx option. To export resources you can specify a base path to export to:

ExportResources

This creates individual .Resx files for each resource set and resource locale in the specified folder. There’s a project mode – Project here and what is appropriate for MVC or standard .NET projects that use Resx resources – or WebForms mode which creates Local and Global resources instead.

As you can see on the resource dialog you can actually use the resource editor to export resources to an arbitrary location on the local disk. This actually lets you export resources to non-Web projects and lets you use the Resource Editor as a general purpose resource editor, which is pretty cool…

Once the resources have been exported you won’t automatically have strongly typed resources. In order to get them you have two choices:

  • Manually set the Resource Generator on invariant .Resx file
  • Generate strongly typed resources from the db resources

Manually set the Visual Studio Resource Generator

The first option is to simply open each invariant .Resx file and set the resource generator to the appropriate Internal or Public class generator as shown earlier on the Resx editor form earlier. You can also do this at the Visual Studio Project file level and select all of the .Resx files, then set the Custom Tool in one go:

ResxGenerator

Recompile and you have your strongly typed resources. Once the .Resx files and strongly typed resource files exist, you can simply re-export when you have changes and those changes will update the Resx files. Recompiling will re-generate the strongly typed classes automatically so you’re good to go – it’s a one time configuration thing.

Note that it’s entirely possible to work with database resources for editing purposes only and then simply dump the resources out to Resx as you make changes for testing and deploying. You don’t actually have to run with db resources in a live environment using this approach. Live db resources are useful if you want to change resources in real time while the application is running and see the changes reflected immediately. Otherwise exporting to Resx files offers a good option that provides all the features you expect from resx features (portability as part of the compiled code, always available etc.).

Export Strongly Typed Classes from Web Db Resource Editor

The other option is to export Resx resources and then also generate the strongly typed classes from the Web Resource Editor interface as shown earlier. When the strongly typed classes have been exported you can specify that you want resources served from Resx files instead.

To make this work you’ll have to set one switch on application startup:

protected void Application_Start() {
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes);
GeneratedResourceSettings.ResourceAccessMode = ResourceAccessMode.Resx;

}

This directs the Property retrieval to look for resources in Resx files using the static resource manager. This works exactly the same as strongly typed Resx resources but you have a single step to generate this class and setting.

So now if you want to switch between db resources and resx resources you can simply comment/uncomment the above flag.

Summary

As you can see Westwind.Globalization can work great in ASP.NET MVC and there are many options of how you can work with resources using this tool. You can run entirely with Db resources, or you can choose to import .Resx resources, edit them and then run your production code with standard .Resx resources with just a couple of extra steps. You have lots of choices on how you can run your localized resources and the localization tasks with this library.

Version 2.0 brings a number of big improvements and is much more focused on the MVC scenario since that paradigm has pretty much taken over. WebForms users don’t need to fret though: All the WebForms specific features like ResourceProvider, Meta Resources and Resource expressions, designer  support etc. all continue to work.

Version 2.0 is in late beta and packages are available on NuGet, but since this is a beta make sure you allow Pre-Release packages to be loaded. The current release is beta 3 which released last night and I hope to get the final release out in the next couple of weeks at the latest.

Resources

© Rick Strahl, West Wind Technologies, 2005-2015

by Rick Strahl at March 17, 2015 11:53 AM

Alex Feldstein

March 16, 2015

FoxCentral News

March at Chicato FUDG: SaaS

 Chicago FUDG is pleased to announce that Michael Birnholz will be presenting his tools and techniques in creating a successful automotive commerce 'SaaS' business based upon VFP, WebConnect, MySQL and the various other tools needed to run a business. This is a rare opportunity for current and prospective entrepreneurs to see the components and techniques of another success story of a thriving business and chat with the guy who made it happen. Monday 16 March 2015 at 5:30 pm; join us at the Merchandise Mart, Suite 1212 (at '1871'), 222 W Merchandise Mart Plaza, Chicago. Full details available on our website at http:/www.ChicagoFUDG.com. We hope you can make it!

by Chicago FoxPro Users and Developers Group at March 16, 2015 05:23 PM

March at Chicato FUDG: SaaS

 Chicago FUDG is pleased to announce that Michael Birnholz will be presenting his tools and techniques in creating a successful automotive commerce 'SaaS' business based upon VFP, WebConnect, MySQL and the various other tools needed to run a business. This is a rare opportunity for current and prospective entrepreneurs to see the components and techniques of another success story of a thriving business and chat with the guy who made it happen. Monday 16 March 2015 at 5:30 pm; join us at the Merchandise Mart, Suite 1212 (at '1871'), 222 W Merchandise Mart Plaza, Chicago. Full details available on our website at http:/www.ChicagoFUDG.com. We hope you can make it!

by Chicago FoxPro Users and Developers Group at March 16, 2015 02:23 PM

Alex Feldstein

FoxProWiki

ChicagoFUDG

Editor comments: March 2015 meeting details
FUDG stands for FoxPro User / Developer Group. This one is based in Chicago, IL. Visit our web site at www.ChicagoFUDG.com !

Leaders:
Michael Hogan
Randy Bosma Speaker Agitator
Jeff Simon Treasurer jeff@datamarkcorp.com
Tom Corrigan Secretary (his FUDG e-mail: tom@corrigan.com)
Greg Gershuny gel4it [at} hotmail {dot] com

Bill Drew Past President bill.drew@sbcglobal.net

Monthly Meetings:
When: Chicago FUDG normally meets on the third Monday of each month, unless it collides with a major event. The meeting room is normally accessible at about 5:15 PM; presentation starts at shortly after our 'business chatter' and introductions at 5:30.
Where: 1871 at the Merchandise Mart suite 1212 (enter from Orleans on the west side of the building and take the west elevators to the 12th floor). When you arrive at the 1871 front desk (adjacent to the west elevator bank) ask to be directed to the FoxPro meeting in the IMSA classroom. Reasonable ($11) parking is available 1 block north of the Orleans Street (west) entrance of the Merchandise Mart.

March 16, 2015 03:55 AM

March 15, 2015

Alex Feldstein

March 14, 2015

Alex Feldstein

March 13, 2015

Sandstorm's Blog (Home of ssClasses)

Give Hope, Give a Hand, Change Lives

Inbetween my work, foxite forum, posting some humor to make some people laugh at FB, I was surprised when someone suddenly popped me up on my mobile phone yesterday via fb messenger.  Said someone introduced herself as a friend of my niece on my cousin and that she is trying hard to reach her, was not able to on that moment and searched for a relative instead in the hope of reaching her outright, then found my fb account and popped me.

The purpose of the message, I later realized is about her desire to include her friend (my  niece) among the possible list of recipients of a so-called LN-4 Foundation.

Being polite and as her claim is to help my cousin's niece, I answered some of her questions.  But when she began asking me about some personal info pertaining to my relative, I was suddenly on guard.

In these days of hardships, there are new scams now and then in my country (my Mom has been a victim herself once of a dugo-dugo gang scammers where a material portion of her savings were lost); so while in conversation, I began the process of slowly prying out some information which can help me decide whether the concern is genuine or just a scam.  And at the same time using the power of internet, I took a short investigation.

In just a few minutes, I found the Philippine-based organization she mentioned to me, reached the persons listed as officials there, briefly skimmed some posts on their wall (they have FB account), and decided to seek permission to post their cause here.


So what is this about?


This is about spreading further the news about Ellen Meadows Prosthetic Hand Foundation, a non-profit organization spearheaded by Ernie Meadows and the late Margie Meadows who passed away late last year.

Brief Histories

LN-4 Foundation

LN-4 is actually "For Ellen, reversed), the daughter of industrial designer Ernie Meadows and his late wife, Margie.  Ellen died young at an early age of 18 in a vehicular accident.  The purpose of the Foundation is to provide, as a gift, prosthetic hands for those who were injured by landmines, work accidents, electricity, acts of violence or a congenital condition; in different parts of the worlds. 

For a more thorough reading, I will refer you to these:

http://www.ln-4.org/history.lasso
http://goldbeachrotary.com/service-projects/world-projects/ln-4
http://hosted.verticalresponse.com/406331/101a24c69f/1763500573/1b134b7498/
http://wallstreetrotary.org/ln-4-prosthetic-hand-project/


LN-4 Foundation Philippines

Began in September of 2014 in the country and is currently based in Panay Island.  It is spearheaded by these people as Ambassadors to the Philippines:

  • Grace Cabato, the LN-4 Director for Team Philippines 
  • husband Rey Cabato, the Deputy-Under Director and Expediter
  • Rease Wold, the Deputy Director 
  • wife Liza Wold as Secretary
  • Marlone & Agustin Cartagena  


Prior to LN-4 establishment in the Philippines, Rease Wold, a retired US Air Force personnel, married to Liza Wold, a former Child and Youth Program Assistant at Fort Lewis Army Base Child Care Center; was originally approached by a friend to help supervise a Non-Government Relief operation for the victims of Yolanda Typhoon under the name PRAY (Provincial Relief Aide for Yolanda), a name concocted by Rease Wold himself.  And with the help of the Philippine Army, some more institutions and volunteers in the Philippines, said non-profit organization were able to reach desolate areas requiring the much needed help.

During said time is when they met The LN-4 Director for Philippines, Grace Cabato.   Grace (was a charge nurse in the Medical ICU at the Queens Medical Central in Honolulu) and Rey Cabato (Retired US Navy) who have their roots in Dao, Capiz, now residing in Hawaii; learned that their baranggay is being overlooked on the relief mission for Yolanda victims.  So they decided to personally fly back to Philippines as volunteers themselves to hand out relief goods.  And that is the time the Cabatos and the Wolds path crossed.  Later, LN-4 Foundation Philippines was born and started providing joy to countless citizens who needs those prosthetic hands.

Here is a brief article about this:  http://panaynewsphilippines.com/2014/11/16/give-hope-give-a-hand/


Psychological Impact

I was once in a vehicular accident myself.  In my teens, I used to ride a Yamaha Enduro 125 motorcycle and said accident broke my femur (thigh bone) in half.  Finding myself lying in the asphalt road and feeling something is wrong in my feet, I lifted it up and my knee fell to my chest. My thigh was broken in half.  Being a realistic person, I prepared myself outright to a possible amputation.  Luckily it never reached that stage that while my femur's growth is somewhat distorted inside, I can walk now without a noticeable limp (though in reality the right foot is a bit longer now than the other).

During the time of recuperation, I became so irritated.  I got angry for nothing and is constantly on a high voice.  When after my mom cried (I am still single back then), I realized my mistakes, apologized and explained to her the psychological impact of losing something that we normally don't pay much attention to; like simple act of walking.  Heck, I dreamt constantly during those times that I am running and it felt sooo good that I'll wake up with a smile on my lips; then the reality hits me and I am back to my sour but more controlled mood!  So in a way, I can empathize to the hardships that our fellow feel without one or two hands.

And in this regard is why I wanted desperately to write this up here, the main purpose is for my readers to be made aware that there is this organization who are tirelessly and selflessly giving away free prosthetic hands for those in need. And like what their slogan says, they are giving hopes to those who need a hand, literally.


How to Reach LN-4 Foundation Philippines

What is more admirable is that said organization is requesting anyone to help them find recipients for their artificial hands.  So if you have someone in mind, then there are two ways to reach them:

- Via Facebook: https://www.facebook.com/groups/692740154144827/
- Via Mobile:  contact their secretary/webmaster, Liza Wold, at (0917) 301-9101 or (0918) 657-1021

Let us all help spread the news!  While this write-up is focused on the Philippine sector, please check again their main webpage at http://www.ln-4.org, to know if now your country is currently on their list. Anyone who knows of someone who needs a prosthetic hand, feel free to contact the above.


Special Thanks to Menaya Samar who upon learning of this foundation, has done her best to to reach my cousin's niece; braving a possible distrust on the good intention upon doing so. As well as to her friend Jing Faren Leonardo, who shared her the news and asked her to think of someone who might need a prosthetic hand.  Special thanks also to countless volunteers working behind the scene on LN-4 Foundation and some more non-profit organizations.  More power to you guys!


"Be thankful for what you have. You have no idea how many people would love to have what you got"


 Michelle Villaflor Amante

by Jun Tangunan (noreply@blogger.com) at March 13, 2015 07:02 AM

Alex Feldstein

March 12, 2015

Rahul Desai's Blog

Alex Feldstein

March 11, 2015

Alex Feldstein

March 10, 2015

CULLY Technologies, LLC

Tips for starting your own Xojo Users Group

I’m a long-time believer in users groups. I gain so much knowledge, not only learning Xojo, but learning other related technologies as well such as communications, database issues, security, etc.

Here’s some tips, not in any particular order:

  1. Try to find Free meeting space. Yes, this is a tough requirement. Sometimes a company will be a “sponsor” and allow you to meet in their conference room. We haven’t been that lucky. We meet at a restaurant that fits the bill. More details below.
  2. Private meeting room. We’ve met at some restaurants that were too loud. This one (unfortunately for them?) is quiet.
  3. Central location. Atlanta is huge and people come from all over. Two of our attendees come from Tennessee. A central location is a must, as we learned the hard way.
  4. Reasonably priced food. Developers aren’t all rolling in the money. I’m one of those low rent kinda developers.
  5. Variety of food. Vegetarians can be anyone and anywhere. It’s worth being sensitive to their needs. Yes, even a BBQ house can have something on their menu for anyone.
  6. Power. Curiously, computers need power. I typically bring extension cords and power strips not only for the presenter, but for the attendees too. It’s surprisingly hard to find outlets in the dining area of restaurants.
  7. Internet access. A luxury but a nice one. The restaurant we use allows us onto their Internet. Some people will hesitate to attend if Internet access isn’t available. It’s easy nowadays that people have phones that can act as hot-spots, but a high speed Internet access is always more stable with better speeds.
  8. Free/good/safe parking. A must for me. It burns me to pay for parking. This rules out most of downtown Atlanta, unfortunately. Many times the “parking lot talks” are of as much technical and business value as the presentation.
  9. Projector. Some locations have a Flat Screen TV that we use as a monitor. At times we have borrowed someones projector. Most of the time, I just bring a monitor. They’re light, reasonably priced, and fit on the table. Our group is small and everyone seems to be able to see the monitor just fine.
  10. Be ready to start small. For a several of our first meetings, it was just me and another developer. Even after all this time, we’ve grown to about 5-7 people on a good month.
  11. Publish your topics ahead of time. I need to do better with this. Publish your topics months ahead so people on the fence need to say “Yeah, I really need to go to May’s meeting. I need to learn more about that topic.”
  12. Be ready to prepare all of the presentations. They don’t need to be fancy but when you are getting started, you’re going to be doing the presentations.
  13. When your attendees talk about their experience say “That sounds like that would make a great topic. Would you be willing to make a presentation on that next month or the month after that?” Even if it isn’t about Xojo, it can be about a related technology.
  14. Let Xojo and Monkeybread Software help get the word out. Both have offered to do a mailing to their customers.
  15. Use the forums to post in the events area.
  16. Consider getting a website. Meet-up is expensive but instantaneously gets the word out to area people. We didn’t go that way. One of our members donates the website space and we run a WordPress based web site with an email plugin that allows us to email our members.
  17. Email your members! I send out a notice a week ahead, and then another email the day of the meeting. Yes, people forget and forget often.
  18. BE CONSISTENT! This one is key. Hold your meeting every month. We meet on the second Monday. Partly because this is a slow day for the restaurant. We meet each and every month. Be prepared to hold a meeting, each month, for an entire year. Be prepared to dine alone if no one shows up. That’s okay. Xojo is a small community and it takes time to grow the trust and value of a users group.

There’s some tips on how to start a Xojo users group. Xojo as a company can only do so much in getting the word out about Xojo as a development tool. It’s good for us as a community and good for us as individuals to spread the word about Xojo as a cross-platform development tool for Windows, Mac, Linux, Web and now iOS!

by kcully at March 10, 2015 02:16 PM

Alex Feldstein

Photo of the Day


Dale Chihuly glass art at Miami's Fairchild Tropical Gardens

by Alex Feldstein (noreply@blogger.com) at March 10, 2015 05:00 AM

March 09, 2015

Alex Feldstein

Photo of the Day


Dale Chihuly glass art at Miami's Fairchild Tropical Gardens

by Alex Feldstein (noreply@blogger.com) at March 09, 2015 05:00 AM

March 08, 2015

Alex Feldstein

Photo of the Day


Dale Chihuly glass art at Miami's Fairchild Tropical Gardens

by Alex Feldstein (noreply@blogger.com) at March 08, 2015 06:00 AM

March 07, 2015

Alex Feldstein

Ford Trimotor flight

Two weeks ago the Local EAA Chapter 620, helped bring two vintage aircraft to Miami: A 1929 Ford Trimotor and a 1943 Boeing B-17
I was part of the organization and a volunteer in the field at Miami Executive Airport - KTMB (formerly Kendall-Tamiami Airport)

It was a fun-filled weekend, helping marshal the Ford Trimotor, collecting ticket from paying passengers for their flight and of course taking pictures.

Here are some of the pictures of the Ford Trimotor and my flight in it. The B-17 images will follow later.























It was a privilege to be able to fly in this piece of living history of aviation. We plan to bring her back to Miami next January. If you come and visit, or if you see the Ford flying in your area, give it a try! You'll love it.

by Alex Feldstein (noreply@blogger.com) at March 07, 2015 11:55 PM

FoxProWiki

VNC

Editor comments: ultravnc website token by some Japanese, uvnc.com is the proper website
Point of Wiki Protocol please: flag your changes with # U # ( but without the spaces) to let people know what, on this long and likely Category Needs Refactoring topic has changed. From memory, I can't tell. Thanks! - ?tr

VNC stands for Virtual Network Computing. It is, in essence, a remote display system which allows you to remotly control the machine (keyboard/mouse, run apps...) from anywhere on the Internet and from a wide variety of machine architectures.

This is an especially good tool for talking someone through a set of steps over the phone. You can explain what you are doing while they watch the actions occur on their screen. They will either have to run a VNC server while you run the client, or you can run the server on a demo box (or your developent box, but I would not let any of my clients on my main box...) so that both of you can see what they are doing.

If you hit the server's port 5800 with a webbrowser (http://ser.ver.ip.adr:5800) the server will supply a java client that will allow the web browser to control the server. It is slower than the .EXE client, but it works.

It does not do printer redirection - use an IP based printer - (I forget what thats called)

For you firewall folks: The Server (host/WinVnc.exe) listens on port 5900 and optionally 5800 for Java. The Client (viewer/VncViewer.exe) listens to 5500 to establish a connection from a server. The Java viewer is downloaded from the server on port 5800, but it then connects to the server 5900. These are the defaults; the VNC server and viewer ports are all configurable, either in setup dialogs or by passing the port on the command line.

It's best to use VNC over SSH for better security. You can do this both using a VNC viewer and a browser. All you need to do is forward some local ports on your machine through the SSH tunnel to the ports on the machine running the VNC server.

Say you've set up the VNC server on machine Bob to use display Y (default is 0).

Now you want to access machine Bob via your local PC over SSH using the VNC viewer.

Establish you SSH connection and set up port forwarding as follows:

local port 595Y to Bob port 590Y
Then connect to VNC server localhost:5Y

If you instead want to use your browser to connect to the VNC server, you need to do the following:

Establish your SSH connection and set up port forwarding as follows:

local port 590Y to Bob port 590Y
local port 585Y to Bob port 580Y
Then go to URL http://localhost:5850 in your browser

If you are using Linux the SSH command would look something like:

ssh -1 -x -C -L 5900:Bob:5900 -L 5850:Bob:5800 "ssh server"

It's free, no pay!

March 07, 2015 09:45 PM

Alex Feldstein

Photo of the Day


Honda Dream 300ss - 1965
2015 Dania Vintage Motorcycle Show

by Alex Feldstein (noreply@blogger.com) at March 07, 2015 06:00 AM

March 06, 2015

Alex Feldstein

Photo of the Day


Miami Executive airport.
Note the B-17 "Aluminum Overcast" parked by Landmark Aviation (orange building)

by Alex Feldstein (noreply@blogger.com) at March 06, 2015 06:00 AM

March 05, 2015

Craig Bailey

Sony SmartEyeglass

So much gold here, as reported by VentureBeat and Re/code.

Sony’s new SmartEyeglass developer edition glasses seem like an April Fools video accidentally released a few weeks early.

My favourite comment is from Kenneth Li, editor in chief at Re/code:

It’s like wearing a kick-me sign. … And nothing says “future” like a HOCKEY PUCK.

The post Sony SmartEyeglass appeared first on Craig Bailey.

by Craig Bailey at March 05, 2015 10:53 PM

Sandstorm's Blog (Home of ssClasses)

Windows OSK inside our Form

Have shared earlier an embedding technique of a 3rd-party app called Virtual Keyboard with codes of  Vilhelm-lon Praisach (with his permission) because while I don't need it, others who used to frequent my blog may.

But since I wanted to find out also how to embed the nasty elusive built-in On-Screen Keyboard (OSK) of Windows which yesterday gave me a lot of frustration as surprisingly it is harder to control than said Free Virtual Keyboard, gleaming new codes from Vilhelm I decided to renew my failed attempts on how it can be done.  Sometimes though when I do try to control things I do not need yet like this one, in the midst of it I wish I should have simply banged my head on the table; for again it seems I am unnecessarily stressing myself  on something I myself do not need nor use (yet).

Anyhow, while finding ways like this sometimes makes my blood pressure go up due to frustrations, in the end when I find a way, I felt a bit of contentment as that is another understanding (to an extent) of these somewhat elusive WinAPIs.   I have yet fully understood these things and just relies on my observations and trials and errors; but I think I am slowly getting there.

After adopting some technique and codes used by Vilhelm I am able to successfully embed OSK within our form under XP OS.  However, trying the same codes inside Windows 7 renews my frustration as said OS does not respect the settings I have done earlier.

Finally, here are the codes that work on both XP and Windows 7 (32-bit, I do not have 64-bit to test it to):

* OSK inside VFP Form XP/Win 7 32-bit

Declare Integer FindWindow In user32;
      STRING lpClassName, String lpWindowName

Declare Integer GetWindowLong In User32 Integer HWndInteger nIndex

Declare Integer ShellExecute In shell32.Dll ;
      INTEGER hndWin, ;
      STRING cAction, ;
      STRING cFileName, ;
      STRING cParams, ;
      STRING cDir, ;
      INTEGER nShowWin

Declare Integer SetWindowLong In user32 Integer HWnd,;
      INTEGER nIndex, Integer dwNewLong

Declare Integer SetWindowPos In user32;
      INTEGER HWnd,;
      INTEGER hWndInsertAfter,;
      INTEGER x,;
      INTEGER Y,;
      INTEGER cx,;
      INTEGER cy,;
      INTEGER uFlags

Declare Integer SetParent In user32;
      INTEGER hWndChild,;
      INTEGER hWndNewParent

Declare Integer SetFocus In user32 Integer

Clear

Public oForm
oForm = Createobject('form1')
oForm.Show()

Define Class form1 As Form
      Height = 400
      Width = 900
      Caption = "OSK Inside VFP Form"
      Desktop = .T.
      AutoCenter = .T.

      Add Object text1 As TextBox With;
            top = 20, Left = 10, Width = 100, Height = 28

      Add Object tmr As Timer With Interval = 100

      Procedure KeyPress
            Lparameters nKeyCode, nCtrlShift
            If nKeyCode = 27
                  Thisform.Release
            Endif
      Endproc

      Procedure Load
            ShellExecute(0,'open','osk.exe','','',1)
      Endproc

      Procedure tmr.Timer
            Local nOSKHeight
            nOSKHeight = 250  && initial OSK height
            nHwnd = FindWindow(Null,'On-Screen Keyboard')
            lnStyle = GetWindowLong(m.nHwnd, -16)
            SetWindowLong (m.nHwnd, -16, Bitset(m.lnStyle,30))  && remove menu
            SetWindowLong(m.nHwnd, -16, Bitxor(m.lnStyle, 0xCF0000))
           
            * In Windows7, OSK is not positioned properly until you do this first and do another below later
            SetWindowPos(m.nHwnd, 0, 0, Thisform.Height-m.nOSKHeight,Thisform.Width, m.nOSKHeight,  0x0020)
           
            SetParent(m.nHwnd,Thisform.HWnd)
            SetWindowPos(m.nHwnd, 0, 0, Thisform.Height-m.nOSKHeight,Thisform.Width+10, m.nOSKHeight,  0x0020)
            This.Enabled = .F.
            SetFocus(Thisform.HWnd)
      Endproc
Enddefine

Some difference in attitude:

  • on XP, it can be resized on-the-ply; on Window 7 it is fixed size
  • on XP  version of OSK,  there is no word suggestion; while on Windows 7 there is 
Here are images showing the difference in appearance and attitude on both OS mentioned:






Afterthought:

If you noticed on the final SetWindowPos, I added 10.  That is because Windows 7 has thicker border than XP and that is used to counter or compensate for the thickness difference.  You can perform an OS() function to determine whether that extra 10 can be added or not.   

Hope this and Vilhelm's will help you on your on screen keyboard needs.  Cheers!


by Jun Tangunan (noreply@blogger.com) at March 05, 2015 06:28 AM

Alex Feldstein

Photo of the Day


Morning routine
Aluminum Overcast B-17
Miami Executive Airport

by Alex Feldstein (noreply@blogger.com) at March 05, 2015 06:00 AM

Rick Strahl's Web Log

Cordova and Visual Studio CODE Magazine Article

Looks like my "Taming Mobile Apps with Cordova and Visual Studio" article went live recently. If you want to find out how to use the new and pretty awesome Visual Studio Tools for Apache Cordova for building Web based, hybrid Mobile apps, this article is a great starting point. The article gives an overview of Cordova and then walks through examples with special focus on building iOS apps.

by Rick Strahl at March 05, 2015 02:14 AM

Cordova and Visual Studio CODE Magazine Article

Nice – looks like my Cordova with Visual Studio article went live today in CODE Magazine as the cover article:

I’ve been doing quite a bit of hybrid Cordova development in the last few months with a couple of customer projects as well as a couple of pet projects. I’ve been really impressed with the tooling that Visual Studio provides for building and testing Cordova apps, especially for iOS devices. This article reflects my experiences specifically with a focus on the iOS development and debugging cycle applied to a small sample project.

I created a small sample app that is described in the article and provided on GitHub for you to play with:

The app is a small AngularJS application that runs with local data. I’ve used this app for a number of different samples including MVC, SPA, Web API and vNext examples, so if you’ve followed some of my other articles you probably find this sample familiar. For Cordova, this sample was modified a bit to be more mobile friendly and adapt better for different mobile device formats.

Anyway, go check out the article – I think it’s a good (and long) one.

Resources

© Rick Strahl, West Wind Technologies, 2005-2015
Posted in Mobile  Cordova  Visual Studio  

by Rick Strahl at March 05, 2015 12:14 AM

March 04, 2015

Sandstorm's Blog (Home of ssClasses)

On-Screen Keyboard for POS

On a POS system, since we are dealing with touch screens, then we need to have a keyboard on screen so our users, in addition to barcode scanning, can do other more works.  And for that what we normally do is create our own on-screen keyboards.  Or utilize the built-in OSK that comes along with Windows that can be simply called via RUN /N OSK.EXE.

What is more appealing though is to make said OSK appear to be really a part of our form and this can be done via embedding said OSK.EXE within our form.  However, embedding Microsoft's OSK is easier said than done.

Good news then, here is an alternative to Microsoft's OSK (On-Screen Keyboard) that can be easily embedded inside our forms.  Further good news is that this one is free: http://freevirtualkeyboard.com/

For the embedding need inside our form, I will refer you to the codes  graciously shared to us by a good friend Vilhelm-Ion Praisach.  In addition to the tricks he used there, I like his subtle touch here on the usage of a timer instead of my SLEEP() way on the embedding 3rd party apps within our forms blog.




Codes:

* Author:  Vilhelm-Ion Praisach
* Date: March 4, 2015

Declare Integer ShellExecute In shell32 Integer hWindow, String lpOperation, String lpFile, String lpParameters, String lpDirectory, Integer nShowCmd
Declare Integer SetParent In User32 Integer HWnd, Integer ParenthWnd
Declare Integer FindWindow In user32 String lpClassName, String lpWindowName
Declare Integer GetWindowLong In user32 Integer HWnd, Integer nIndex
Declare Integer SetWindowLong In user32 Integer HWnd, Integer nIndex, Integer dwNewLong
Declare Integer SetFocus In user32 Integer
Declare Integer SetWindowPos In user32 INTEGER HWnd, INTEGER hWndInsertAfter, INTEGER x, INTEGER Y, INTEGER cx, INTEGER cy, INTEGER uFlags
Declare Integer GetWindowThreadProcessId in Win32API Integer hWnd, Integer @lpdwProcessId
Declare Integer OpenProcess in Win32API Integer dwDesiredAccess, Integer bInheritHandle, Integer dwProcessID
Declare Integer TerminateProcess in Win32API Integer hProcess, Integer uExitCode

Clear
Public ofrm
ofrm = Createobject("MyForm")
ofrm.Show()

Define Class MyForm As Form
      Width = 900
      Height=430
      hOsk = 0
      nOskHeight = 200
      ShowWindow = 2
      Desktop = .T.
      AutoCenter = .T.
      Add Object txt As TextBox
      Add Object cmd As CommandButton With Top = 50 , Caption = "\<Click"
      Add Object tmr As Timer With Interval = 300
     
      Procedure Load
            = ShellExecute(0, "open", "freevk.exe", "", "", 1) && this should be inside among your VFP paths
      ENDPROC
     
      Procedure tmr.Timer
            LOCAL nStyle
            ThisForm.hOsk = FindWindow (.Null., "Free Virtual Keyboard (www.FreeVirtualKeyboard.com)")
            nStyle = GetWindowLong (ThisForm.hOsk, -16)
            SetWindowLong (ThisForm.hOsk, -16, Bitset(m.nStyle,30)) && set child
            SetWindowLong (ThisForm.hOsk, -16, Bitclear(m.nStyle,31)) && remove popup
            SetParent(ThisForm.hOsk, Thisform.HWnd) && change parent
            SetWindowLong (ThisForm.hOsk, -16, BITAND(m.nStyle,2^32-1-0xCF0000)) && remove the title bar
            SetWindowPos(ThisForm.hOsk, 0, 0, ThisForm.Height-ThisForm.nOskHeight,ThisForm.width, ThisForm.nOskHeight,  0x0020+0x0040) && move to the bottom of the form and show

            This.Enabled = .F.
            SetFocus(Thisform.HWnd) && set focus to the VFP window
      ENDPROC
      PROCEDURE destroy
            LOCAL lnProcessID
            lnProcessID = 0       
            GetWindowThreadProcessId(ThisForm.hOsk, @lnProcessID)       
            TerminateProcess(OpenProcess(1, 1, m.lnProcessID) , 0)
      ENDPROC
      PROCEDURE resize
            SetWindowPos(ThisForm.hOsk, 0, 0, ThisForm.Height-ThisForm.nOskHeight,ThisForm.width, ThisForm.nOskHeight,  0x0020+0x0040+0x0010) && move to the bottom of the form, and show, and SWP_NOACTIVATE
      ENDPROC

Enddefine



Hope this helps!  Cheers!

by Jun Tangunan (noreply@blogger.com) at March 04, 2015 11:29 PM

FoxCentral News

Philadelphia VFP User Group meets March 10

The next meeting of the Philadelphia VFP User Group will be Tuesday, March 10 at 7 PM in room 104, DeVry University, 1140 Virginia Drive, Fort Washington, PA. As usual, feel free to bring some dinner and come as early as 6:30 PM. Member Bill Fitzgerald will present ?SSRS 101: SQL Server Reporting System for beginners?

by Philadelphia Visual FoxPro User Group at March 04, 2015 06:20 PM

Philadelphia VFP User Group meets March 10

The next meeting of the Philadelphia VFP User Group will be Tuesday, March 10 at 7 PM in room 104, DeVry University, 1140 Virginia Drive, Fort Washington, PA. As usual, feel free to bring some dinner and come as early as 6:30 PM. Member Bill Fitzgerald will present ?SSRS 101: SQL Server Reporting System for beginners?

by Philadelphia Visual FoxPro User Group at March 04, 2015 04:20 PM

Alex Feldstein

March 03, 2015

VisualFoxProWiki

UpcomingEvents

A place to list upcoming Visual FoxPro events like conferences, meetings, user groups, open training sessions...
Closest at the top please, and please remove past events.

March 03, 2015 09:58 PM

VFP Philly

March 10: Bill Fitzgerald on SQL Server Reporting Services



Our next meeting will be Tuesday, March 10 at 7 PM.

Member Bill Fitzgerald will present “SSRS 101: SQL Server Reporting System for beginners”:

SSRS – SQL Server Reporting System has been evolving quietly over the past decade and has now emerged as Microsoft’s preferred tool for preparing and displaying database reports. It is the default reporting system for SQL Server and .NET, and also is a powerful standalone report generator. At the same time there has been a decline in the support for the  integration of Crystal Reports with .NET, creating a need that Microsoft has moved to fill.

SSRS is well supported, there are many tutorials available and perhaps most important for some of us – it’s free!

This presentation will look at SSRS from a VFP programmer’s point of view and show how one VFP programmers made the journey to learning enough about SSRS to do most of the things we do with the VFP report writer. (Alas- not all- but most.) It will also show a few things that can’t be done with the VFP report writer.


 

by Tamar E. Granor (noreply@blogger.com) at March 03, 2015 09:44 PM