Finding Files From Within WinCE Applications

Environment: WinCE, C++

In this lesson, we'll begin to explore the techniques for allowing the user to find and access files. The main tool for this job is our old Win32 friend, the Common File Dialog, but it works a little differently under CE. Our vehicle for examining its functionality is a demo application called FileOpen. The main sample code file for this app is provided separately, so we'll just include snippets of key code in the discussion that follows. To see the snippets in context, refer to the accompanying source file.

Getting Started

The business of the FileOpen example all starts to happen when the IDM_OPEN_FILE message is received in WndProc(). First, we launch ChooseFilePathDlgProc(), which allows the user to choose a path. This path will be used to initialize the common file open dialog.

case IDM_OPEN_FILE:
  DialogBox( hInst, 
             TEXT("Pathnames"), 
             hWnd,
             ChooseFilePathDlgProc );

Next, we call ChooseFilePermsDlgProc() to give the user a choice of file open permissions. These permissions will regulate the action of CreateFile() when we attempt to open the file.

DialogBox( hInst, 
           TEXT("FILE_PERMISSIONS"), 
           hWnd,
           ChooseFilePermsDlgProc );

In DoFileOpen(), we display the common file dialog and allow the user to choose an existing file or specify a filename to use in opening the file.

lpof = DoFileOpen( hWnd, FILE_OPEN );
if(!lpof)
{
  break;
}

Finally, we attempt to open the file with a call to CreateFile(), and report our success or failure to the user with MessageBox().

//Open the file for reading.
hTestFile = CreateFile( (LPTSTR)lpof->lpstrFile,
            GENERIC_READ | GENERIC_WRITE ,
            FILE_SHARE_READ, NULL, dwFileCreateFlags, 
            FILE_ATTRIBUTE_NORMAL, NULL);
if( !hTestFile )
{
  MessageBox( hWnd, TEXT("Try Different Permissions"),
              TEXT("File Open Failed"), MB_OK );
  break;
}
if( dwFileCreateFlags == OPEN_EXISTING )
    MessageBox( hWnd, lpof->lpstrFile,
                TEXT("Existing File Opened"), MB_OK );
{

}
if( dwFileCreateFlags == CREATE_NEW )
{
  MessageBox( hWnd, lpof->lpstrFile,
              TEXT("New File Created"), MB_OK );
}

When we are finished, we close the file like this:

CloseHandle(hTestFile );
break;

Let's take a close look at the initialization of the ChooseFilePathDlgProc() dialog. In this function, the first thing we have to do is detect the platform type. This allows us to correctly load the list box with directory name strings.

case WM_INITDIALOG:
hWndList = GetDlgItem(hDlg,IDC_PATHNAMES );
//Init paths list based on platform type
memset( &tszPlatType, 0x0, sizeof(tszPlatType));
rc = SystemParametersInfo( SPI_GETPLATFORMTYPE, 
                           sizeof(tszPlatType),
                           &tszPlatType, 0);
if( (lstrcmp( tszPlatType, TEXT("Jupiter") ) == 0 )
              ||
  ( lstrcmp( tszPlatType, TEXT("HPC") ) == 0 ) )
{
  iBaseStringID = IDS_HPC_PATH1;
  iMaxStringID  = IDS_HPC_PATH11;
}

if( lstrcmp( tszPlatType, TEXT("Palm PC") ) == 0 )
{
  iBaseStringID = IDS_PPC_PATH1;
  iMaxStringID  = IDS_PPC_PATH7;
}

The pathname strings are stored consecutively in the resource file. By initializing the iBaseStringID with the lowest string ID and the iMaxStringID with the highest, we can load them with a loop. Notice that we use a CE-style call to LoadString(), which returns a pointer to the text of the string in the resource file. The return from this function must be cast to (LPCTSTR) when it is used in this way because its declaration specifies a return type of int. The word immediately preceding the returned address contains the string length.

for( i = iBaseStringID; i < iMaxStringID; i++ )
{
  lpszPathString = (LPCTSTR)LoadString( hInst, 
                                        i, 
                                        NULL, 
                                        NULL);
  lpbStrlen = (LPBYTE)lpszPathString;
  lpbStrlen -= 2 * sizeof( BYTE );
  wCharCnt = (short int)(*lpbStrlen);

We use the string length to allocate a buffer on the local heap. Notice that the string length is reported in characters, not in bytes. Also, we add one to this length because we need space for a terminating null. This brings us to why we are allocating a buffer in the first place—the strings stored in the resource file are not null terminated, so you can't use them directly in calls that require a terminal null.

lpszPath = (LPTSTR)LocalAlloc( LPTR, 
                 (wCharCnt + 1) * sizeof(TCHAR));
LoadString(hInst, i, lpszPath, (int)wCharCnt + 1);

Finally, we insert the pathname string at the end of the list and free the buffer.

  ListBox_InsertString(hWndList, -1, lpszPath);
  LocalFree(lpszPath);
}
  return TRUE;

In the grand scheme of things, the next bit of information we acquire from the user is the file open permissions. There's nothing unusual about the dialog code for this, so we won't dissect it here. However, our dialog offers only non-destructive permission choices. When we open the file with a call to CreateFile(), we'll look at a more complete list.

In DoFileOpen(), we initialize the structure that configures the common File Open dialog.

Notice that we specify a filter string for the dialog by using the TEXT macro. The sequence following the first null ( \0 ) inside the quoted string sets the filter pattern the dialog will use to discriminate the filenames it makes visible to the user.

const LPTSTR pszOpenFilter = 
             TEXT ("All Documents (*.*)\0*.*\0\0");

We allocate an OPENFILENAME structure, and we also allocate a buffer for the filename. The pointer to the filename buffer is a member of the OPENFILENAME structure, and the application is responsible both for initializing the pointer and providing space for the filename.

// Allocate space for the OPENFILENAME struct
lpof = (LPOPENFILENAME)LocalAlloc( LPTR,
                                   sizeof(OPENFILENAME));
if (!lpof)
  { goto FAIL;}

// Allocate space for the FILENAME string
pszFileName = (TCHAR*)LocalAlloc(LPTR, MAX_PATH);
if (!pszFileName) 
  { goto FAIL;}

This bit of code that follows is actually superfluous in this case because the LPTR argument to LocalAlloc() causes the allocated block to be zero initialized. However, if this were a stack-based buffer, you'd want to set the first element to null to display a blank edit control for the filename. Conversely, if you want a default file name displayed, initialize the filename buffer with that string.

// Make the first char null, as we don't want the
// dialog to init the filename edit ctl.
// pszFileName[0] = '\0';

Setting the lpstrInitialDir member of the OPENFILENAME structure to the path the user chose from the pathname dialog causes the file open dialog to be initialized with the filenames in that directory. All types of files will be displayed, because that is what we specified above, in the content of pszOpenFilter.

// Initialize File Open structure.
lpof-&lStructSize     = sizeof (OPENFILENAME);
lpof->hwndOwner       = hWnd;
lpof->lpstrFile       = pszFileName;
lpof->nMaxFile        = MAX_PATH;
lpof->lpstrFilter     = pszOpenFilter;
lpof->lpstrInitialDir = (LPCWSTR)&szPath[0];

Once again, we have a bit of superfluous code, at least for this particular case. We test a flag passed to the function to see whether we are opening a file or saving one. I included this to show two things: First, the initialization of the OPENFILENAME structure is nominally the same in either case. (The exception here is if you have different file extensions or initial directory locations for the two operations.) And second, it is a good practice to warn the user before allowing them to overwrite an existing file.

  if (iOpenSaveFlag ==  FILE_SAVE)
{
  //prompt for overwrite, send files to sync directory
  lpof->Flags = OFN_OVERWRITEPROMPT;


  if( !GetSaveFileName (lpof))
  {
     lpof = NULL;
  }
}
else
{

  if( !GetOpenFileName (lpof))
    {
      lpof = NULL;
    }

The DoOpenFile() function then returns either a fully initialized OPENFILENAME structure, or null if there was an error.

Next, we open the file with a call to CreateFile( ).

//Open the file for reading.
hTestFile = CreateFile( (LPTSTR)lpof->lpstrFile,
                       GENERIC_READ | GENERIC_WRITE,
                       FILE_SHARE_READ, 
                       NULL, 
                       dwFileCreateFlags,
                       FILE_ATTRIBUTE_NORMAL, 
                       NULL);

The parameters to CreateFile(), in the order shown, are the filename, the requested type of access, the sharing mode, a NULL placeholder for the unsupported security attributes parameter, the file creation mode, the file attribute flags, and another NULL placeholder for the unsupported hTemplate parameter. Here's a table of the supported values for file creation, along with their meanings, followed by a similar table of file attributes.

Table 8-1 CreateFile() File Creation Flags

Create Flag Constant Effect of Flag
CREATE_NEW Creates a new file and fails if the specified file already exists.
CREATE_ALWAYS Creates a new file. If the file exists, the function overwrites it and resets attributes.
OPEN_EXISTING Opens the file or fails if the file does not exist.
OPEN_ALWAYS Opens the file, if it exists, or creates the file if it doesn't exist.
TRUNCATE_EXISTING Opens the file and truncates it to zero length. Fails if the file does not exist.

Table 8-2 CreateFile() Attributes

Attribute Constant Effect of The Attribute
FILE_ATTRIBUTE_ARCHIVE Mark files for backup or removal.
FILE_ATTRIBUTE_HIDDEN File will not be included in an ordinary directory listing.
FILE_ATTRIBUTE_NORMAL No other attributes set. Overridden by any other attribute flag.
FILE_ATTRIBUTE_READONLY File is read only—can't be written or deleted.
FILE_ATTRIBUTE_SYSTEM Used exclusively by the operating system.

One last bit about file names. If you want to be able to store the maximum number of files on a PC Card device, use filenames of uppercase letters, in 8.3 format. PC Cards use more than one physical entry in their file allocation table to store long filenames and names with mixed case.

Looking Ahead

In our next lesson, we'll look into techniques for reading and writing files.

About the Author

Nancy Nicolaisen is a software engineer who has designed and implemented highly modular Windows CE products that include features such as full remote diagnostics, CE-side data compression, dynamically constructed user interface, automatic screen size detection, and entry time data validation.

In addition to writing for Developer.com, she has written several books, including Making Win 32 Applications Mobile.

Downloads

Download Source - 5 Kb


About the Author

Nancy Nicolaisen

Nancy Nicolaisen is a software engineer who has designed and implemented highly modular Windows CE products that include features such as full remote diagnostics, CE-side data compression, dynamically constructed user interface, automatic screen size detection, and entry time data validation. In addition to writing for Developer.com and CodeGuru, she has written several books, including Making Win 32 Applications Mobile.

Comments

  • budget-priced clarisonic can revive your incrustation

    Posted by iouwanzi on 06/05/2013 10:55pm

    [url=http://www.australiaclarisonic.com/clarisonic-mia]clarisonic mia[/url] Man skal også kigge efter den ekstraordinære træk ved støj isolation i deres trådløse hovedtelefoner som en måde at tage glæde i høj kvalitet musik. Begrebet støj isolation er ikke det samme som at billige beats lady gaga By Dre Detox Special Limited Edition Professional Headphones Canada af støjdæmpning. Funktionen af støj isolation gør det muligt for ikke en eneste plet af eventuelle baggrundslyde, som en individuel taler ved siden af billige dre beats dig at blande i din lytning. Dette virkelig er utroligt så langt som du er nødt til at groove i dine egne betingelser. Det er hævet over enhver tvivl, at omdømme i de trådløse hovedtelefoner er på himmelflugt med hver eneste dag, der går. Så er du i øjeblikket i stand til at købe beats af Lady Gaga din første trådløse hovedtelefoner til tv? Forhåbentlig er du, fordi det ville være en skam at gå glip af alle de fremragende programmer og film, som kan blive lyttet til i det antal, du foretrækker simpelthen fordi du ikke har oprettet dine tanker dog. beats by dresolo hd til virkelig at føle meget mere behageligt, gøre bare lidt længere at lede efter de funktioner, du ønsker. Meget bedre endnu, kan du besøge en forhandler og teste nogle ud. Så vil du virkelig føle sig helt sikker, som du er parat til ikke bare købe, men beats by Lady Gaga helt sikkert sætte pris en helt ny trådløs hovedtelefon til fjernsyn. [url=http://www.australiaclarisonic.com/clarisonic-classic]clarisonic classic[/url] Based hovedtelefoner tilbyde lydkvalitet, der er lige så forbløffende. Ideel til nutidens digitale musik, disse hovedtelefoner giver dyb bas, en fed mellemtone, og klar, uforvrænget diskant, så du kan høre hver detail.The on-ear, lukket-back design giver langvarig komfort og en høj grad af naturlig støj isolation . Den enkeltsidede kabel er designet til at give dig masser af slæk mens modstå tangles. Integreret i kablet er Monsters ControlTalk modul, som giver dig en kontrolknap og high-grade mikrofon, ideel til styring musikafspilning, telefonopkald og tage stemmenotater på kompatible iPods, iPhones, og Blackberrys. Den guldbelagt 3,5 mm stik giver bred kompatibilitet med MP3-afspillere, cd-afspillere, computere og meget mere. [url=http://www.miaclarisonicaustralia.org/]clarisonic mia 2[/url] I tilfælde alle ordentlig pleje vedrørende tone sammen med netop hvordan man høre din nuværende lyd og så kan du sætte pris på din BIII ved blot Doctor. Dre Destroy betydelige effektivitet headsets. Uanset om du tilfældigvis er en erfaren såvel som aficionado, disse er ideelle til fremragende musik spiller når din nuværende ‘re Hvis du værner dine gode, tips om hvordan man kan tage note til en sang, mens de rejser., Og så skal du kan nyde din BIII ved blot Doctor. Dre ødelægge højtydende headset. Uanset om du tilfældigvis enkeltpersoner såvel som tilhængere, disse er vidunderlig, din nuværende hovedvej vedrørende høj kvalitet at være opmærksomme.

    Reply
  • Beats by Dr. Dre, din vælger

    Posted by wanzixiao on 06/03/2013 11:21pm

    [url=http://www.kbhretelefonerbillig.webstarts.com/]Køb høretelefoner billig[/url] Samarbejdet om lettelse af Beats by Dre viser sig at være en ganske indbringende forretning for dette selskab, som der er store statistik over salg og tilbagemeldinger er god som derved øger den samlede tilbagemelding af selskabet. Vkhifi.com sikrer, at de produkter, der leveres ordentligt til slutbrugere, og at der ikke er nogen klager. Hvis der er, er draget omsorg for at løse problemet med kunder, der har købt produktet. Selvom de andre sammen med Hovedtelefoner beats aldrig har stået over for en sådan problem og kundernes feedback er generelt god, disse er politikker, der fastsættes af selskabet. Om Vkhifi.com Selskabet Vkhifi.com er én stor vove sig ind i lettelse af beats, der rocke digitale verden. Hovedtelefoner og headsets, som nogle af de allerbedste spillere på det globale marked som DRE, Monster og headsets indikerer, at selskabet har til formål at sætte en høj klasse af forretningssted i et betydeligt kort tidsrum. Virksomheden Formanden erklærede en vandretur i erhvervslivet lønsomhed med indførelsen af disse nye produkter og forventes at nå ganske høj med fremskridt inden for teknologi. [url=http://www.beatsbydrdredanmark.weebly.com/]Beats by dre danmark[/url] ikke blot disse hovedtelefoner kommer beriget med den nyeste teknologiske trends, men de kommer også i trendy stilarter og smukke farver, så de hårde dem kan vælge de hårde farver og resten som pr deres normale valg. Den stereoanlæg kvaliteten af hver af hovedtelefonerne er udestående. “Vi tror på kvalitet, og det er grunden til, vi tilbyder dem i den højeste kvalitet til de mest gennemførlige satser”, erklærede en af bestyrelsesmedlemmerne. Hovedtelefoner beats også omfatte en ny sort, der er på høje ender.Virksomheden ser en stigende kurve af overskud og tager sigte på at nå til en større del af det digitale samfund. [url=http://www.beatsbydrdredanmark.blinkweb.com/]monster beats danmark[/url] Give indsigt i LOCOG tænkning, og måske om ikke dets juridiske team vil reagere forskelligt på Dr Dre har Beats hovedtelefoner stunt, en talsmand sagde dengang: “Vores tilgang til håndhævelse i 2006 loven har altid været fornuftig, pragmatisk og forholdsmæssige.”Vi er nødt til at beskytte rettighederne for vores sponsorer, der har betalt for at få eksklusive associationer til legene i deres sponsorater kategorier. Vi er hård på kommercielt misbrug, men vi ønsker ikke at gøre noget for at dæmpe ægte begejstring og spænding om Games .

    Reply
  • Despatch 2013 a unknown color schematic Nike Sense Max shoes

    Posted by Tufffruntee on 04/25/2013 03:28am

    Qualifying series Nike Breath Max HomeTurf metropolis recently finally comes up, this series in the archetypal Air Max shoes to London, Paris and Milan [url=http://www.nikeskorrea.se/nike-free-run-3-c-62/]nike free run 3[/url] the three paid commendation to the iconic bishopric of Europe, combined with the characteristics of the three cities, Publish Max 1 HYP,Current Max 90 HYP,Mood Max 1 and shoes such as Air Max 95, combined with the Hyperfuse, as wonderfully as a variety of materials, such as suede, Whether you lust after functional or retro-everything. It seems to me that more than Nike [url=http://www.nikeskornatet.se/nike-free-40-v2-c-45/]nike free 4.0 sverige[/url] shoes all supernova meeting decorous signature shoe series, and NSW series, all the leading part color layout of the new Germane to Max Hyperposite exposure. Mine-shaft daybreak brown chroma piqued, hyperfuse, swoosh, and are married at the down of the yellow/orange gradient snap details, lining is a Galaxy in [url=http://www.nikeskornatet.se/nike-air-max-90-c-9/]air max 90 rea[/url] orange archetype garter, acutely beautiful.

    Reply
  • Sample is incomplete

    Posted by marce002 on 11/30/2004 08:45pm

    Please someone can complete the example I can not make it run for pocket pc 2000

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

  • Today's "average" business in general is ever more reliant on technology and the Internet. Mobility is the most often cited business trend that has transformed the way many of us work and communicate. From an IT security perspective, this means that protection methods and tools from even a few years ago are rapidly becoming "unfit for purpose." This guide provides crucial facts to assist you in building a robust business case, meeting the demands of your business, and protecting against threats now and in the …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds