Pelles C forum

C language => Beginner questions => Topic started by: xsilvergs on March 28, 2007, 12:43:24 PM

Title: Old Dog New tricks
Post by: xsilvergs on March 28, 2007, 12:43:24 PM
Hi

I'm new to C and new to my pocketpc but old and a bit slow to learn so please be gentle.

I'm trying to write my first program for my pocketpc and run into a problem, I can add button and edit boxes and make things happen but my program requires a combobox.

Having added a combobox to the DLG_MAIN I've set it as a "Dropdown list" as I want the user to only use items in the list but how do I write/fill the list?

I've search the web for info but must be looking in the wrong places as I've not found anything related.

As I've said earlier I'm new to this so please be as clear as possible.

Thanks for help in advance.
Title: Re: Od Dog New tricks
Post by: JohnF on March 28, 2007, 02:21:54 PM
I don't do the pocketpc but assume it will be the same.

Fill in a  COMBOBOXEXITEM and send the info with SendMessage with the CBEM_INSERTITEM message.

COMBOBOXEXITEM cbei; // the struct
SendMessage(hwndCombo, CBEM_INSERTITEM, 0, (LPARAM)&cbei);

You may need to look at the MSDN library for more explanation.

http://msdn2.microsoft.com/en-us/library/ms771608.aspx

John
Title: Re: Od Dog New tricks
Post by: xsilvergs on March 28, 2007, 04:12:12 PM
Thanks for your reply, I've got it sorted now.
Title: Re: Od Dog New tricks
Post by: DMac on March 28, 2007, 05:21:09 PM
Check out this topic thread:
http://www.smorgasbordet.com/forum/index.php?topic=2062.0
I have posted a link there to a nice demo project using the combobox.
Regards,
David M.
Title: Re: Old Dog New tricks
Post by: xsilvergs on March 29, 2007, 01:57:33 PM
Thank you for info.

I'm moving on very slowly but enjoying every moment, I now have another question now.

How do I use the TabControl as my project needs 3 tabs?

Thanks again
Title: Re: Old Dog New tricks
Post by: DMac on March 29, 2007, 04:23:57 PM
xsilvergs,

Here is a link to another useful demo and article on code project that makes using the tab control easy.

http://www.codeproject.com/win32/Win32SDK_C_TabCtrl.asp (http://www.codeproject.com/win32/Win32SDK_C_TabCtrl.asp)

regards,
DMac
Title: Re: Old Dog New tricks
Post by: JohnF on March 30, 2007, 03:18:52 PM
David, allow me to make a suggestion, all your PellesC projects include the .tag file this makes the zip unnecessarily large.

John
Title: Re: Old Dog New tricks
Post by: DMac on March 31, 2007, 08:02:38 PM
John,

Thanks for pointing that out.

Usually I get rid of the exe and the object files but that one was not obvious to me.

In the future I'll leave the tag out of the zip.

regards,
D Mac
Title: Re: Old Dog New tricks
Post by: xsilvergs on April 02, 2007, 11:16:58 AM
Me again

Is there a list/tutorial for things like, GetDlgItemText as I don't really understand the commands?

Also I'd like to find out how to make the textbox visible and invisible in code, is this posible?

This is all for PPC.
Title: Re: Old Dog New tricks
Post by: xsilvergs on April 04, 2007, 09:06:54 AM
I'm still struggleing, I can't work out how to make an editbox invisible.

Can somebody please help?
Title: Re: Old Dog New tricks
Post by: JohnF on April 04, 2007, 10:04:16 AM
The ShowWindow() API will do it. Look it up on MSDN if you do not know the syntax.

John
Title: Re: Old Dog New tricks
Post by: xsilvergs on April 04, 2007, 11:21:32 AM
Hi John, thanks for reply.

I've looked at this http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/WindowsUserInterface/Windowing/Windows/WindowReference/WindowFunctions/ShowWindow.asp and am none this wiser although I can SW_HIDE.

The example I've been trying to use is from http://www.trajectorylabs.com/win32_dialog_based_application.html . They add a macro like this #define SetDlgItemFocus(hwnd,idCtl)  FORWARD_WM_NEXTDLGCTL((hwnd), GetDlgItem((hwnd),(idCtl)), TRUE, PostMessage) and then I do this SetDlgItemFocus(hwndDlg, IDC_OXY); and the focus is passed.

So for the showwindow I've added this #define SetDlgItemHide(hwnd,idCtl) FORWARD_WM_SHOWWINDOW((hwnd),GetDlgItem((hwnd),(idCtl)), TRUE, PostMessage) and tried adding this SetDlgItemHide(hwndDlg, IDCDEPTH); to implement it, but it doesn't work.

What am I doing wrong? Sorry to appear so stupid but this is my first attempt a writting in C.

Tony
Title: Re: Old Dog New tricks
Post by: JohnF on April 04, 2007, 12:23:54 PM
No need for all those macros - they seem to be confusing you.

On the Microsoft site you would have seen this

BOOL ShowWindow(     

    HWND hWnd,
    int nCmdShow
);

That is the syntax for ShowWindow, now the parameters are hWnd and nCmdShow. Looking down where the parameters are you can see SW_HIDE. Sounds appropriate. So,

ShowWindow(hEditControl, SW_HIDE);

Will do it for you. When you want to show the edit control again use SW_SHOW instead of SW_HIDE.

All controls are in fact windows, btw.

If you don't have the edit control handle use

HWND GetDlgItem(
    HWND hDlg,
    int nIDDlgItem
);

Where hDlg is the handle to the main window or the diloag box.

nIDDlgItem is the control identifier used when you created the control.

For example - if you created the edit window with CreateWindow the 10th parameter was the indentifier, the one before hInstance.

    hwnd = CreateWindowEx( "", "", "", "",
        0, 0, 0, 0, hwndParent, (HMENU)IDENTIFIER, hInstance, NULL);

Or if you used a dialog then there would have been something like this

CONTROL "", ID_FILTER, "Edit", ES_AUTOHSCROLL|WS_BORDER|WS_TABSTOP, 8, 20, 100, 12

Where ID_FILTER was the indentifier.

John
Title: Re: Old Dog New tricks
Post by: xsilvergs on April 04, 2007, 12:44:46 PM
John

Are you saying I only need to add one line to my code like this

ShowWindow(IDCDEPTH, SW_HIDE); where IDCDEPTH is my Editbox

When I do I get this error message

C:\Program Files\PellesC\Projects\Nitrox\main.c(248): error #2140: Type error in argument 1 to 'ShowWindow'; found 'int' expected 'struct HWND__ *'.

Tony


Title: Re: Old Dog New tricks
Post by: frankie on April 04, 2007, 01:18:46 PM
Retrieve the handle of the control window with GetDlgItem:
Code: [Select]
    ShowWindow(GetDlgItem(hDlg, IDCDEPTH), SW_HIDE);
Where  hDlg is the handle of your dialog.
Title: Re: Old Dog New tricks
Post by: JohnF on April 04, 2007, 01:39:47 PM
John

Are you saying I only need to add one line to my code like this

ShowWindow(IDCDEPTH, SW_HIDE); where IDCDEPTH is my Editbox

When I do I get this error message

C:\Program Files\PellesC\Projects\Nitrox\main.c(248): error #2140: Type error in argument 1 to 'ShowWindow'; found 'int' expected 'struct HWND__ *'.

Tony

Just one line, yes.

Frankie has already answered your question but I would like to add that the compile errors are/can be used to debug your mistakes.

"Found int but expected HWND", that was a hint for you. Your identifier is an int, the handle of the edit control is a HWND.

John
Title: Re: Old Dog New tricks
Post by: xsilvergs on April 04, 2007, 01:54:25 PM
Sorry to be making such hard work of this.

If I look under the TAB main.rc, Dialog, I have DLG_MAIN, this carries all the buttons and editboxes

If I add this to my code

ShowWindow(GetDlgItem(DLG_MAIN, IDCDEPTH), SW_HIDE); I get this error message

C:\Program Files\PellesC\Projects\Nitrox\main.c(249): error #2140: Type error in argument 1 to 'GetDlgItem'; found 'int' expected 'struct HWND__ *'.

Tony
Title: Re: Old Dog New tricks
Post by: xsilvergs on April 04, 2007, 02:09:05 PM
Well I've made it disapear with the line ShowWindow(GetDlgItem(hwndDlg, IDCDEPTH), SW_HIDE); . I don't understand hwndDlg but it works.

Thank you all for your help.

Tony
Title: Re: Old Dog New tricks
Post by: JohnF on April 04, 2007, 04:37:38 PM
You need to read up on this stuff. hwndDlg is the handle of your Dialog.

John
Title: Re: Old Dog New tricks
Post by: xsilvergs on April 04, 2007, 09:45:31 PM
John

You wouldn't know how much surfing I've done trying to find relevant material, there is to much on the net.

There is so much that says it's C# but the code is so different to what's in my program, much of the code I've seen is punctuated with full stops where mine here isn't.

Can you recommend something reading that is specific to what I'm using here please.

Thanks for your help.

Tony
Title: Re: Old Dog New tricks
Post by: JohnF on April 04, 2007, 11:04:18 PM
I would recommend reading Petzold's 'Programming Windows 3.1', you can often find it in libraries and if you are lucky there will even be a CD attached.

C# btw, is not the same as C.

John
Title: Re: Old Dog New tricks
Post by: xsilvergs on April 05, 2007, 08:35:58 AM
Thanks for the book recommendation, we have a library here in Poole, I'll have a look at lunch time.

How easy is it to add bitmap images to buttons?

Tony
Title: Re: Old Dog New tricks
Post by: frankie on April 05, 2007, 09:44:39 AM
You can buy the book "Programming windows" through the net. Look at the Petzold's site:
http://www.charlespetzold.com/pw5/ (http://www.charlespetzold.com/pw5/)
Title: Re: Old Dog New tricks
Post by: JohnF on April 05, 2007, 10:44:05 AM
Thanks for the book recommendation, we have a library here in Poole, I'll have a look at lunch time.

How easy is it to add bitmap images to buttons?

Tony

Not difficult.

SendMessage(hBut, (UINT)BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hBmp);

John
Title: Re: Old Dog New tricks
Post by: xsilvergs on April 06, 2007, 10:00:28 AM
Couldn’t find book in library so will order from t’internet.

John, thank you for code sample, my intention is to show a button that has a bitmap instead of the normal text. I’ve read another article here http://www.smorgasbordet.com/forum/index.php?PHPSESSID=becb9f3b89b4072209043fab894a4d53&topic=532.0 and I think the second post in it seems more fitting to what I’d like to do. There seems to be three stages, LoadBitmap, GetDlgItem and SendMessage.

Rightly or wrongly in the main.rc I have a folder called Bitmap, in it is a resource IDR_BMP_ONE which points to a file C:\Program Files\PellesC\Projects\ButtonPic\victor.bmp .

I’ve written this:
LoadBitmapW(ghInstance, MAKEINTRESOURCE(IDR_BMP_ONE));
GetDlgItem(hwndDlg, ID_BUTONE);
SendMessage(HWND(ID_BUTONE), BM_SETIMAGE, IMAGE_BITMAP,IDR_BMP_ONE);

And I get these errors;
C:\Program Files\PellesC\Projects\ButtonPic\main.c(124): error #2066: Illegal use of type name 'HWND'.
C:\Program Files\PellesC\Projects\ButtonPic\main.c(124): error #2068: Found 'struct HWND__ *' expected a function.
C:\Program Files\PellesC\Projects\ButtonPic\main.c(124): error #2140: Type error in argument 1 to 'SendMessageW'; found 'void' expected 'struct HWND__ *'.

I think I understand what each line code is trying to do but don’t understand C yet.

Is it possible for anyone to give me some help please?

Thanks again

Tony

Title: Re: Old Dog New tricks
Post by: JohnF on April 06, 2007, 10:27:01 AM
Tony,

===================
I’ve written this:
LoadBitmapW(ghInstance, MAKEINTRESOURCE(IDR_BMP_ONE));
GetDlgItem(hwndDlg, ID_BUTONE);
SendMessage(HWND(ID_BUTONE), BM_SETIMAGE, IMAGE_BITMAP,IDR_BMP_ONE);
===================

Here is the corrected code. Why are you using LoadBitmapW() ? If you are compiling UNICODE the compiler will sort out which API's to use, weather UNICODE or not.

Code: [Select]
HBITMAP hBitmap = LoadBitmap(ghInstance, MAKEINTRESOURCE(IDR_BMP_ONE));

HWND hBut = GetDlgItem(hwndDlg, ID_BUTONE);

SendMessage(hBut, (UINT)BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hBitmap);

Try to understand what's required. For example you had put the identifier IDR_BMP_ONE instead of the handle to the bitmap that is returned from LoadBitmap. Also ID_BUTONE in the SendMessage API where it required the handle to the button not an identifier.

Here, you are trying to cast an int (ID_BUTONE), to a HWND

SendMessage(HWND(ID_BUTONE), BM_SETIMAGE, IMAGE_BITMAP,IDR_BMP_ONE);

Plus, casting is this way, (HWND)type not the way you had it.

John
Title: Re: Old Dog New tricks
Post by: xsilvergs on April 06, 2007, 09:01:24 PM
Hi John thanks for code.

Prior to this the only coding I've done is for PIC micro's which I have no problems with but C is so different. The code I'd written didn't look right as I couldn't see where the data would be stored, with PIC's I'd put it in a register. I can see from your code where it is held. Hopefully when I get the book things will be clearer.

Any way I've placed your code in just after the case WM_INITDIALOG, no errors now but for some reason my .bmp doesn't appear on the button.

Any ideas?

Tony
Title: Re: Old Dog New tricks
Post by: JohnF on April 06, 2007, 09:24:18 PM
Tony,

You could check the return values of the function calls. Can you use the PellesC debugger yet?

John
Title: Re: Old Dog New tricks
Post by: xsilvergs on April 06, 2007, 09:53:59 PM
If it's just a case of Project, Debug ButtonPic.exe i get a message saying no debug info. If I ok this on the debug tab I see this:
Starting remote debug server
Creating remote process ButtonPic.exe
Process B2DEF46A started
Thread B2E990AA started
Loading ButtonPic.exe at 00010000
Loading shutil.dll at 02D20000
Loading tshres.dll at 7FFE0000
Loading commctrl.dll at 02DE0000
Loading oleaut32.dll at 027D0000
Loading ossvcs.dll at 02750000
Loading aygshell.dll at 02D70000
Loading ole32.dll at 02800000
Loading coredll.dll at 01F60000

Where are the return values? and what should I look for?
Title: Re: Old Dog New tricks
Post by: JohnF on April 06, 2007, 11:09:14 PM
zip up your project and send it to me.

EDIT: I forgot to say that when creating the button you must include the BS_BITMAP style.

Example
Code: [Select]
CONTROL "OK", ID, "Button", WS_TABSTOP | BS_BITMAP, 118, 174, 40, 14

John
Title: Re: Old Dog New tricks
Post by: xsilvergs on April 11, 2007, 10:06:32 AM
I'm back again with what should be very simple.

I'm adding a couple of integars together and want to show them in a message box with some text.

I would like a message box  to show something like this, Your answer is 5. The 5 being the total of the addition.

Is it like this, do I have to convert the int to a string and how do I include it?

      WCHAR wszBuffer[40];
      swprintf(wszBuffer, L"%i", total);
      MessageBox(hwndDlg, L"Your answer is ", L"Addition result", MB_OK|MB_SETFOREGROUND);

Thanks for any help

Tony
Title: Re: Old Dog New tricks
Post by: JohnF on April 11, 2007, 10:14:05 AM
WCHAR wszBuffer[40];
swprintf(wszBuffer, 39, L"%i", total);
MessageBox(hwndDlg, wszBuffer, L"Your answer is ", MB_OK|MB_SETFOREGROUND);

John

Title: Re: Old Dog New tricks
Post by: xsilvergs on April 11, 2007, 10:21:14 AM
Hi John

What I was trying to do have a line of text in the message box that was made up of "Your answer is 5". Is it possible to join text (Your answer is) and the wszBuffer contents together? Something like this, but it doesn't work.

MessageBox(hwndDlg, L"Text" & wszBuffer, L"Addition result", MB_OK|MB_SETFOREGROUND);
Title: Re: Old Dog New tricks
Post by: xsilvergs on April 11, 2007, 11:17:15 AM
I'm still trying but can't combine L"Some text" with wszBuffer into one line.

A little more help would be apreciated.
Title: Re: Old Dog New tricks
Post by: JohnF on April 11, 2007, 11:33:52 AM
WCHAR wszBuffer[40];
swprintf(wszBuffer, 39, L"Your answer is %i", total);
MessageBox(hwndDlg, wszBuffer, L"Title", MB_OK|MB_SETFOREGROUND);

John
Title: Re: Old Dog New tricks
Post by: xsilvergs on April 11, 2007, 11:37:15 AM
Thank you John.

I had just worked it out myself, that's only taken me 3 hours but we got there in the end.
Title: Re: Old Dog New tricks
Post by: xsilvergs on April 11, 2007, 01:26:06 PM
My next question is regarding joining of strings (concatenation).

I've declared str1, str2 and str3 as char, I would like to show the numbers as a string in a messagebox, here is the code I'm trying to use.

case BTN_ANS:
   {
      str1 = "1";
      str2 = "2";
      str3 = (char *)calloc(strlen(str1)  + strlen(str2) + 1, sizeof(char));
      WCHAR wszBuffer[40];
      swprintf(wszBuffer, L"Numbers are ", L"%s", str3);

MessageBox(hwndDlg, wszBuffer, L"My string is", MB_OK|MB_SETFOREGROUND);

Am I going about this in the wrong way and how should I do it?

Thank you
Title: Re: Old Dog New tricks
Post by: JohnF on April 11, 2007, 02:22:29 PM
WCHAR str1[] = L"1";
WCHAR str2[] = L"2";
WCHAR wszBuffer[40];
swprintf(wszBuffer, 39, L"Numbers are %ls and %ls", str1, str2);
MessageBox(0, wszBuffer, L"My string is", MB_OK|MB_SETFOREGROUND);

You should read up on these things, no one is going to answer these simple questions on an ongoing basis.

THIS:
swprintf(wszBuffer, L"Numbers are ", L"%s", str3);

It is the second time you wrote swprintf that way, even after I showed the right way. Try and see what's wrong with it.

John
Title: Re: Old Dog New tricks
Post by: JohnF on April 11, 2007, 02:54:12 PM
Also, one cannot assign characters this way

str1 = "1";

in C that is a no-no.

If the string has room you can copy with this

wcscpy(wchar_t * restrict targetstring, const wchar_t * restrict sourcestring);

Which would be

   WCHAR str1[8]; // 8 is large enough
   wcscpy(str1, L"1");

Or create the string like this

WCHAR str1[] = L"1";

To concatenate

WCHAR str1[] = L"1";
WCHAR str2[] = L"2";
WCHAR * str3; // note the *, str3 is a pointer to an array of WCHAR, but at this point it points nowhere.

With this next line we allocate memory and assign the address to str3. The extra sizeof(WCHAR) is for the double termination of the string
str3 = malloc(wcslen(str1) + wcslen(str1) + sizeof(WCHAR));

strlen() is no good for WideChar strings

Now do it
swprintf(str3, wcslen(str1) + wcslen(str1) + sizeof(WCHAR), L"%ls %ls", str1, str2);

MessageBox(0, str3, L"My string is", MB_OK|MB_SETFOREGROUND);

John
Title: Re: Old Dog New tricks
Post by: xsilvergs on April 11, 2007, 03:04:17 PM
John

Sorry if my questions seem simple but certain examples from the internet etc. don't seem to work. For example the:

swprintf(wszBuffer, 39, L"Numbers are %ls and %ls", str1, str2); won't work for me in pocket pc.

If I write it:

swprintf(wszBuffer, L"Numbers are %ls and %ls", str1, str2); it works fine.

There is probably an explanation for this but I haven't found it yet?

Thanks again for your help

Ps. I'll try your example you've just posted.

Tony
Title: Re: Old Dog New tricks
Post by: JohnF on April 11, 2007, 04:18:13 PM
Ok, maybe it is different on WINCE.

Have you read the C FAQ? Might help with general stuff.

http://www.faqs.org/faqs/C-faq/faq/

John
Title: Re: Old Dog New tricks
Post by: JohnF on April 11, 2007, 04:43:38 PM
Tony,

There is a mistake in my code when calculating the string length, you need to double for UNICODE, maybe best to create another variable.

WCHAR * str3;
int strLenght = ((wcslen(str1) + wcslen(str1)) * 2) + sizeof(WCHAR);
str3 = malloc(strLength);

Also you should free the memory when it is no longer required.

free(str3);

John
Title: Re: Old Dog New tricks
Post by: xsilvergs on April 23, 2007, 02:26:04 PM
Can somebody give me a clue please with my PocketPC problem?

I've now written some code to convert, sort and add, a text document containing ascii characters but I need to save the file with a new name.

The new name for the file is written in an Editbox. I then use GetDlgItemText to retieve the file name, this is in the format LPWSTR.

I am then trying to use f=fopen function with the name from the Editbox but of course it doesn't work because this want's a char *.

Could somebody explain how to convert please.

code used:
case BTN_SFA:
         GetDlgItemText(hwndDlg, TXT_FILE, wszBuffer, NELEMS(wszBuffer));
      
      f=fopen(????????????,"w");
      {
      for(d=0;d<=e;d++)
         fprintf(f,"%i,",data[d]);
      }
      fclose(f);

Thanks

Tony
Title: Re: Old Dog New tricks
Post by: sp00n on April 23, 2007, 03:00:30 PM
Code: [Select]
char *filename;
wcstombs(filename, wszBuffer, wcslen(wszBuffer)+1);
f = fopen(filename, "w");
if it isn't work try this:
Code: [Select]
wchar wczBuffer[260];
... //your code
char filename[260];
wcstombs(filename, wszBuffer, 260);
f = fopen(filename, "w");

Title: Re: Old Dog New tricks
Post by: xsilvergs on April 23, 2007, 03:36:08 PM
sp00n

Thank you. The char filename[260] works the other sample doesn't. I had tried using the wcstombs prior to writting but I couldn't get it to work. All I need to do is understand it now.

Thanks again

Tony
Title: Re: Old Dog New tricks
Post by: sp00n on April 23, 2007, 05:08:31 PM
As I remember that functions (like mbstowcs, wcstombs, wcscpy, wcscat etc) needs agrs like wchar[] or char[], 260 is a constant for PocketPC named MAX_PATH (max length of filename), that why I use it :)
Good luck with your coding :)
Title: Re: Old Dog New tricks
Post by: xsilvergs on April 26, 2007, 02:37:42 PM
Can somebody point me in the right direction please.

When I've created my PocketPC programs how do I install them with a shortcut in the start menu and/or in Programs?

My PPC's run Windows Mobile 2003 and 2003SE