Wednesday, March 21, 2012

[ Dot Net Remoting ] - Using Configuration (config) files in Server and Client side

1. Introduction

In this article, I will show how to use the "Configuration File" on server and client side of the remoting applications. Instead of developing the application from scratch we will take the already developed one and make use of the configuration file. We take a previous article example (Server Activated, Singleton) and use it here.

You can take that example from download link from this article => Refer

2. Configuration File (Server)

To add a configuration file to the server project, right-click the project name in the solution explorer, then select add item from the context menu. From the displayed dialog, chose the Application configuration file as shown in the below picture.

Adding Dotnet Application Configuration File
Fig 1. Adding Dotnet Application Configuration File


In the solution explorer, you can now see a file named app.config. Double click the file to open it. Then enter the details as shown below:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
            <system.runtime.remoting>
                        <application>
                                    <service>
                                                <wellknown mode="Singleton" type="SingletonServer.RegVotes, SingletonServer" objectUri="RegVotes"      />
                                    </service>
                                    <channels>
                                                <channel ref="tcp" port="1334"   />
                                    </channels>                             
                </application>
            </system.runtime.remoting>
</configuration>

Now this configuration file is the better alternative for the programmable configuration that already exists in the server project. So we need to comment them. In the program.cs file the following code is commented out:

//Server 006: Create and Register TCP Channel
//TcpServerChannel SrvrChnl = new TcpServerChannel(13340);
//ChannelServices.RegisterChannel(SrvrChnl, false);

//Server 007: Register the Remote Class so that the Object can go
//and sit on the Remote pool
//RemotingConfiguration.RegisterWellKnownServiceType(typeof(SingletonServer.RegVotes), "RegVotes", WellKnownObjectMode.Singleton);

Note that the commented piece of code uses the TCP channel 13340 and registers the same for accepting the client requests. So the code portion marked as Server 006 tag is replaced by the configuration file’s channel section. In the configuration file, I changed the port to 1334.

Then we registered our remote object using the RegisterWellKnownServiceType function call. In the above code, this is done in the Tag Server 007. We commented this also as we have it in the configuration file under the Service section.

Now look at the code below, that loads the remote server using the configuration file shown above. Note that the configuration file we added is App.config and what we specified to configure function is something different. This is not a magic. Go to the folder in which the build operation deployed the server executable. In the same folder, you will see that build operation deployed configuration file also with a different name app.config. Even the name is different, the content is same. So we referred this deployed file name in the call RemotingConfiguration.Configure

//Server 006,007: Host the Server from configuration file
RemotingConfiguration.Configure("SingletonServer.exe.config", false);

You can now launch the server application as before.

3. Configuration File (Client)

No need to explain much here. Below is the app.config file added in the same way as we did in for the server project:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
            <system.runtime.remoting>
                        <application>
                                    <client>
                                                <wellknown type="SingletonServer.RegVotes, SingletonServer" url="tcp://localhost:1334/RegVotes"  />               
                        </client>
                        </application>     
             </system.runtime.remoting>
</configuration>

And, the commented code + newly added code are shown below:

//Client 003: Get the Proxy for the Remote object from the server
//remobj = (RegVotes)Activator.GetObject(typeof(RegVotes), "tcp://localhost:13340/RegVotes");
RemotingConfiguration.Configure("SingletonClient.exe.config", false);
remobj = new RegVotes();

Note that previously we used the Activator.GetObject. And we commented that as we have it in the configuration file now. However, in the commented code we get the required object after specifying the remote object, communication channel and port number. Now, after loading the configuration file we can create the object using the new operator. This will create the object on the server, and you have a proxy here for making the method calls in the remote object.

4. Careful when using configuration file

If you make mistakes in the configuration file, we will not get compilation error as most of the configurable parts are tied to the runtime. In that case, creating the object using the new RegVotes() will create the object from the available in the client reference itself.

Use the below picture to know the association between client and server. Making a mistake will give trouble later.

A Sample Dot Net Remoting Configuration File (Client & Server)
Fig 2. A Sample Dot Net Remoting Configuration File (Client & Server)

Source Code: Download

Tuesday, March 20, 2012

[ MFC ] - Restoring MainFrameWnd in VC++ using GetWindowPlacement and Registry


1. Introduction

In this article, I will show how can we preserve the application main window in terms of its size and position with respect to the desktop. The structure win32 structure WINDOWPLACEMENT will hold the information related to the window size and its position. We can fill this structure for a given window by making a call to GetWindowPlacement. The same way we can set the new position and size of the window using the SetWindowPlacement. OK, how do we preserve the window size and position? We should write this structure to the registry when the window is closed. And when the application is re-opened, we will restore the window state by reading the structure that written to the registry when the window was closed.

2. Creating the Sample App

You can apply the technique going to be explained in this article to any application. For now, we will do it for the SDI type of MFC Application. Create a new MFC Application. In the wizard, state you need SDI Application without document and view support. Accept the default for the rest of wizard steps. As we do not ask for the document and view support we will get the below specified initial classes.



The application is changed with a comment tag: Sample <xx>
Here xx is the step no. You can use find in files to search for the Text //Sample<One Blank Space Here>. Below is the result of changes made the Initial Wizard generated application.



3. Setting the Key
Search Tag: //Sample 01

The first step is setting a registry key name for the application. Go to the application class InitInstance function and make the change as shown below:

//Sample 01: Set the Value to the meaningful as given in the above comment
//SetRegistryKey(_T("Local AppWizard-Generated Applications"));
SetRegistryKey(_T("MsTechArticles"));

The key we set is called MsTechArticles. You can set a different key as you like. Usually in an organization environment, it will be usually the company name. In this same function, we are going to read the registry to restore the window state. But, now we will move to writing the registry.

Before we move on, go to the application property page (Right client project, chose property) and set the character set to Multibyte as shown below:


Why are we doing this? To avoid specifying the string literals like _T("MsTechArticles") as in the above piece of code. Once we specify the above property we can specify the string as you do in the VS 6.0.



4. Writing WINDOWPLACEMENT to registry
Search Tag: //Sample 02, //Sample 03, //Sample 04

Before start writing our task we should add a function that will get called when the application window is closed. To do that first we should provide the handler for the message WM_CLOSE. This message will be sent when the application window is closed. Below video shows how we add a handler for this message.

Video 1: Watch Here


1) First, we asked to write the toolbar state to the application registry. Remember we already specified our application key in the Sample 01 tag.

//Sample 02: Save the tool bar state to Registry
this->SaveBarState("TBAR STATE");

As MainFrame window already provides a function SaveBarState the job of saving the toolbar position and docking side become easy. But, to store the window position and state we need to write data registry ourselves.

2) OK. To write the data of window position and its size we need to open the registry key first. Now, we may come to a situation that the Key does not exist (For the first time) or it already exists (From Next time onwards). So what we do here is first try to open the specific key on a specific path. If it is not there, then create the one. The functions RegOpenKeyEx, RegCreateKeyEx are used to make the key ready before start writing the data.

//Sample 03: Open the Registry Key when Exists or Create the One
HKEY reg_key;
DWORD disposition;
if (RegOpenKeyEx( HKEY_CURRENT_USER, "Software\\MsTechArticles\\WindowPos",           0,         KEY_WRITE,       &reg_key   )!=        ERROR_SUCCESS )
{
RegCreateKeyEx( HKEY_CURRENT_USER, "Software\\MsTechArticles\\WindowPos",  0,"", REG_OPTION_NON_VOLATILE ,                                   KEY_ALL_ACCESS, NULL,  &reg_key,  &disposition);
}

In the above code first, we tried to open the Registry key Software\\MsTechArticles\\WindowPos under the root key HKEY_CURRENT_USER. If that key not available in the registry then we are creating the one. The first parameter is the Root key and next parameter (Second) specifies all the sub-keys. The option REG_OPTION_NON_VOLATILE specifies that we want to persist the information written between the login and logout of the system. Have look at the Picture below to have an understanding of the registry structure:



In the above piece of code, we are trying to open key till the subkey level only. We are not yet coming to the Value Key and Value like the one shown above.

3) We used functions to open, create the registry keys. Once the key is ready, we can place Value Key and actual value in the opened key. Have a look at the below code:

//Sample 04: Query the Window Position,size then store it in Registry
WINDOWPLACEMENT strucWP;
this->GetWindowPlacement(&strucWP);
::RegSetValueEx(reg_key, "WinPos", 0, REG_BINARY, (BYTE *) &strucWP, sizeof(WINDOWPLACEMENT));
::RegCloseKey(reg_key);

First, we used the GetWindowPlacement function to read the Window position and size with other details. The information retrieved is packed in the structure called WINDOWPLACEMENT. So this packed information then is written to the registry using the RegSetValueEx win32 API function call. From function parameter, we can see that the Value Key is WinPos, the actual value is the content of the WINDOWPLACEMENT structure in Byte stream format.

OK. Now, whenever the user closes the window, its position and size are written to the registry. We will move to reading this structure from the registry so that we can restore its size and position.

5. Read WINDOWPLACEMENT from Registry
Search Tag: //Sample 05, //Sample 06, //Sample 07, //Sample 08

1) In the Application class, a private function is added. This function will take care of restoring the window position by reading the window placement structure from the registry. Below is the declaration:

//Sample 07: Declaration
private:
            void ReStoreWindow();

2) Next, the state of the toolbar is restored by making use of the LoadBarState member function available in the CMainFrame. The perfect place to make a call to that function is OnCreate as we need to load the toolbar status when the Main application window is created. Below is the code:

//Sample 08: Load the Toolbar State saved in the OnClose Handler
this->LoadBarState("TBAR STATE");

3) The below function is written to restore the Main window when the application is opened.

//Sample 06: Restore the Window Position and size
void CWinPlacementSampApp::ReStoreWindow()
{
            //Sample 06_1: Declaration & Initialization
            UINT retvalue;
            HKEY reg_key;
            DWORD type = REG_BINARY;
            WINDOWPLACEMENT strucWP;
            DWORD size = sizeof(WINDOWPLACEMENT);

            //Sample 06_2: Read the WindowPlacement from Registry and restore the Window position when
            //                                                            it was closed.              
            retvalue = ::RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\MsTechArticles\\WindowPos", 0, KEY_READ, &reg_key);
            if (retvalue == ERROR_SUCCESS )
                        retvalue = ::RegQueryValueEx(reg_key, "WinPos", 0, &type, (LPBYTE) &strucWP, &size);

            //Sample 06_3: When the read of WINDOWPLACEMENT no succeeded, go with the default showwindow
            if(retvalue == ERROR_SUCCESS)
                        m_pMainWnd->SetWindowPlacement(&strucWP);
            else
                        m_pMainWnd->ShowWindow(SW_SHOW);

}

Here, we used the RegOpenKeyEx function to open the Key. Once the key is opened, we read the value for WinPos using the RegQueryValueEx function call. When any of these calls fails, we can restore the Window and hence we go with the default ShowWindow function call of the member variable of CMainFrame. When these calls succeed, we have a valid WINDOWPLACEMENT structure with us. Supplying this structure to SetWindowPlacement will restore the window to its previous (When it was closed) position with the same size.

If you want to know more details about the parameters, use the MSDN (If you own one) or go with Google and it will bring you to online MSDN.

4) OK. The function for restoring the window is ready! Where is it used? It is used in the Application class’s InitInstance    function. In that function, the call to ShowWindow is commented out and a call to the function described in the previous point is made. Below is the code:

// The one and only window has been initialized, so show and update it
//Sample 05: Read the stored values from the Registry and set it=>
//pFrame->ShowWindow(SW_SHOW);
ReStoreWindow();


The test run for the attached sample is recorded as a video.

Video 2: Watch Here


Source Code : Download

Monday, March 12, 2012

[ MFC ] - Using the PreCreateWindow override, hide the maximize & minimize mainframe buttons


1. Introduction


In this article, we will create Single Document Interface (SDI) application for a start. Then we will have a look at the CREATESTRUCT structure to modify the style of the displayed window.


2. About the Sample


Look at the Screenshot below:



The screenshot shows a portion of the MFC generated SDI Application. In this sample, we modified the default SDI by changing the CREATESTRUCT that is passed to the PreCreateWindow function. The following modifications are applied to the sample:

1) Minimize and Maximize boxes at the upper right corner of the window (Not shown in screen shot) are removed.
2) The entire SDI application is displayed as fixed size dialog. That means the dialog can not be resized.


3. Create MFC SDI Application


Creating the MFC SDI Sample is shown in the below video. The MFC Framework for SDI application with document and view support will create four classes for you. These classes are explored in detail in a separate article on Document view architecture.


When you run the Application, you will see default SDI as shown in the below screenshot:


The Untitled says that the document is not yet given a valid title. The dialog is resizable and at the upper right-hand side, you can see Minimize, Maximize, and close button.

4. The PreCreateWindow Override

The CMainFrame class already overrode the PreCreateWindow for you. All you need to do is navigate to the function and start writing the code. The function signature is shown below:

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

This function is called by the MFC framework before creating the window. So it is a perfect place to intercept the window creation and make the modification to the default window style. Look the parameter. The function already supplied with the created structure and it expects that the client (We are a client to the MFS Framework as we are making use of their classes. In this case the CMainFrame) will inform the changes through the CREATESTRUCT parameter cs. Also, note that the parameter is received by reference so the changes we make on this structure are reflected back to the caller. The caller will then draw the window with the changes we apply. Have a look at the video to Navigate to the PreCreateWindow function (If you are first time user of MFC):

Video 1: Watch Here

The PreCreateWindow function modified as shown below:

// TODO: Modify the Window class or styles here by modifying
//  the CREATESTRUCT cs
// Sample 01: Hide the document title
cs.style = cs.style & (~ FWS_ADDTOTITLE );
//Sample 02: To remove Maximize and Minimize box of the window
cs.style = cs.style & ( ~(WS_MAXIMIZEBOX | WS_MINIMIZEBOX ));
//Sample 03: Avoid resizing the document. Make it fixed size
cs.style = cs.style & ~WS_THICKFRAME;

In the above set of statements, we revoked some of the already added styles to the style member of CREATESTRUCT. Say, for Example, the style member already had the WS_THICKFRAME applied to it. To remove that style we used the bitwise negation on the WS_THICKFRAME constant. Then we applied that negated (Bit inverse) content style by performing the bitwise AND (&).

First, we removed the document title (Marked in yellow in the above picture) from the window caption area. Then we revoked the Minimize and Maximize box from the window. Finally, the window is made fixed size.

The below video shows final Sample after making the above-said changes in the PreCreateWindow function.
Video 2: Watch Here
Source Code : Download
Like this site? Tell it to your Firend :)