Re: New uninstaller #1/3
Jonathan Ernst wrote: Here is the new uninstaller. This is the first patch out of 3 of the new installer. Thanks to Dmitry Timoshkov for helping me a lot with my first win32 program. Changelog: - use dialog instead of window Hey Jonathan, Your patch is still quite big. You've rewritten every function in uninstaller.c, as far as I can tell. Is there any reason you need to do that to convert to using a dialog? I think you may need to break it up even further to get it applied, but the final decision isn't mine. I'd encourage you to write a patch that only converts the window to a dialog, and get that applied first. When that is done, you can think about unicode conversion. Mike
Re: New uninstaller #1/3 (RESEND)
Jonathan Ernst [EMAIL PROTECTED] writes: +#include resource.h +#include En.rc The new resource.h file is missing. -/* BINRES uninstaller.ico */ -UNINSTALLER ICON MOVEABLE uninstaller.ico -/* { - '00 00 01 00 01 00 20 20 10 00 00 00 00 00 E8 02' - '00 00 16 00 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 04 00 00 00 00 00 00 02 00 00 00 00' You can't remove the icon data, this is needed for the BINRES stuff. -- Alexandre Julliard [EMAIL PROTECTED]
Re: New uninstaller
Le jeudi 03 mars 2005 21:51 +0900, Mike McCormack a crit : Hi Jonathan, You'll have more success getting this applied if you send each step as a seperate patch. I suggest starting by sending a single patch that converts the uninstaller to use a dialog instead of a window, adds a dialog resource in English and does nothing else. Ok, once everything works I'll try to split it up as much as I can. Once that patch is accepted, move onto the other tasks you have listed above. One step at a time makes the patch easier to review, and reduces the chance that a single line mistake will stop your entire patch from going in. Additionally, there's no need to change the name of main.c to uninstaller.c, that will just make it harder to see what has changed between versions. I thought it would be more homogeneous as taskmanager, winecfg where using program_name.c files and that most of this file was rewritten by the way. But I renamed it back in my latest test patch. Thanks for your comments ! signature.asc Description: Ceci est une partie de message =?ISO-8859-1?Q?num=E9riquement?= =?ISO-8859-1?Q?_sign=E9e?=
Re: New uninstaller
Jonathan Ernst wrote: Additionally, there's no need to change the name of main.c to uninstaller.c, that will just make it harder to see what has changed between versions. I thought it would be more homogeneous as taskmanager, winecfg where using program_name.c files and that most of this file was rewritten by the way. But I renamed it back in my latest test patch. It would look nicer if it was called uninstaller.c, but renaming files in CVS should be avoided as much as possible. It makes patch management (doing diffs and reverting patches) difficult. Mike
Re: New uninstaller
Jonathan Ernst [EMAIL PROTECTED] wrote: I tried to fix every char-WCHAR I though was worth it; please have a second look at it. The problem now with unicode is that when I try to strstr my token with the element of the list (entries[i].descr) it works only with the first letter (before to use unicode it was working very well). You can see the same problem (one letter .descr) when using the unintaller with --list. The second problem is that since I use unicode for the argvs, whatever argv I give I get the --list branch. Your main mistake is that you are trying to handle ASCII strings with old APIs, you can't do that. Unicode requires a completely different set of APIs, and win32 provides one. +/* +TELL ME: IS IT STILL NEEDED WITH UNICODE ??? len = WideCharToMultiByte(CP_UNIXCP, 0, entries[i].descr, -1, NULL, 0, NULL, NULL); As I have said it already, you need to convert unicode strings to the encoding of the underlying system before printing strings on console. CP_UNIXCP is supposed to do exactly that task. +descr = HeapAlloc(GetProcessHeap(), 0, len); +WideCharToMultiByte(CP_UNIXCP, 0, entries[i].descr, -1, descr, len, NULL, NULL); */ +printf(%s|||%s\n, entries[i].key, entries[i].descr); +/*HeapFree(GetProcessHeap(), 0, descr);*/ You have to HeapFree a HeapAlloc'ed memory block. It's better to use W versions of APIs even if it's not strictly required. +if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, REGSTR_PATH_UNINSTALL, 0, KEY_READ, hkeyUninst) != ERROR_SUCCESS) RegOpenKeyExW in this case. { - MessageBox(0, Uninstall registry key not available (yet), nothing to do !, appname, MB_OK); - return 0; +MessageBox(0, sRegistryKeyNotAvailable, sAppName, MB_OK); MessageBoxW in this case. if (!entries) - entries = HeapAlloc(GetProcessHeap(), 0, sizeof(uninst_entry)); +entries = HeapAlloc(GetProcessHeap(), 0, sizeof(uninst_entry)); Quite strange formatting. strcpy(key_app, REGSTR_PATH_UNINSTALL); strcat(key_app, \\); p = key_app+strlen(REGSTR_PATH_UNINSTALL)+1; You shouldn't use string APIs supposed to handle ASCII strings. Use lstrcpyW,lstrcatW and lstrlenW in this and all other cases. sizeOfSubKeyName = 255; -for ( i=0; - RegEnumKeyExA( hkeyUninst, i, subKeyName, sizeOfSubKeyName, - NULL, NULL, NULL, NULL ) != ERROR_NO_MORE_ITEMS; - ++i ) +for (i=0; RegEnumKeyExA( hkeyUninst, i, subKeyName, sizeOfSubKeyName, NULL, NULL, NULL, NULL ) != ERROR_NO_MORE_ITEMS; ++i) RegEnumKeyExW in this case. +static const WCHAR DisplayNameW[] = {'D','i','s','p','l','a','y','N','a','m','e',0}; +strcpy(p, subKeyName); lstrcpyW +RegOpenKeyExA(HKEY_LOCAL_MACHINE, key_app, 0, KEY_READ, hkeyApp); RegOpenKeyExW +res = CreateProcess(NULL, entries[i].command, NULL, NULL, FALSE, 0, NULL, NULL, si, info); CreateProcessW +prevsel = SendMessage(hList, LB_GETCURSEL, 0, 0); SendMessageW and many,many,many others. Make sure to pass correct arguments to all the changed APIs. For better understanding of what is going on add the following as the very first line in main.c: #define __WINESRC__ -- Dmitry.
Re: New uninstaller
Jonathan Ernst [EMAIL PROTECTED] wrote: I fixed/changed many things regarding unicode. It seems that now both outputing to the console and case insensitive find as you type feature (re-)work. I fixed most warnings, but there are still 4 lines that I couldn't fix (173, cast entries[numentries-1].command to LPBYTE as you do 3 lines earlier. 206, wrong STARTUPINFO declaration, you need a unicode one with W suffix. 215, you can't use sprintf to print to a WCHAR string, use win32 API wsprintfW instead. 429). Can someone help me ? slen = strlenW(String), plen = strlenW(Pattern); better use official API lstrlenW. /* find start of pattern in string */ while (toupper(*start) != toupper(*Pattern)) You can't use toupper with unicode strings. I can't suggest a win32 equivalent from the top of my head, you need to find out. pptr = (WCHAR *)Pattern; There is no need for a cast here. while (toupper(*sptr) == toupper(*pptr)) same as above. Last but not least, since these changes the uninstaller crashes (very) often. I have an unhandled exception when retrieving some apps from the uninstall key and I don't know what cause this: err:seh:EXC_DefaultHandling Unhandled exception code c005 flags 0 addr 0x77ecf5d4 Very likely a common error happening often in the process of unicodification: buffer overflow due to not a correct memory allocation, or a not correct initialization of a variable pointing to a buffer length (size of buffer in bytes vs. WCHARs). For better understanding of what is going on add the following as the very first line in main.c: #define __WINESRC__ When adding this line the compilation fails with this message: main.c:194: error: `STARTUPINFO' undeclared (first use in this function) Are some include(s) missing ? That's the point. I'd prefer that you could figure out that on your own. Hint: look at the headers, and you will see that all those STARTUPINFO, lstrcpy, RegOpenKey are not the real API names, but just macros depending whether UNICODE is defined or not. In Wine using API macros is deprecated, personally I'd prefer to not use them in programs/* either. Do you think I'm near the target ? Definitely very close. -- Dmitry.
Re: New uninstaller
Le mardi 08 mars 2005 23:29 +0800, Dmitry Timoshkov a crit : Jonathan Ernst [EMAIL PROTECTED] wrote: [...] Thanks, fixed. You can't use toupper with unicode strings. I can't suggest a win32 equivalent from the top of my head, you need to find out. It seems that CharUpperW works well. [...] Last but not least, since these changes the uninstaller crashes (very) often. I have an unhandled exception when retrieving some apps from the uninstall key and I don't know what cause this: err:seh:EXC_DefaultHandling Unhandled exception code c005 flags 0 addr 0x77ecf5d4 Very likely a common error happening often in the process of unicodification: buffer overflow due to not a correct memory allocation, or a not correct initialization of a variable pointing to a buffer length (size of buffer in bytes vs. WCHARs). Thanks for the hint. I found the allocation problem. [...] Fixed Now everything works; thanks for your step by step help; I hope that what I'me learning now will let me make more additions to Wine ! But: It is even possible to uninstall more than one app at a time, but I wish that when an uninstaller has finished to uninstall an application the list is updated, but it's not. What's and where's a clean way to do it ? Please find attached main.c's diff. Jonathan P.S. Do I really have to split this new uninstaller in different patches as nearly everything changed ? Index: main.c === RCS file: /home/wine/wine/programs/uninstaller/main.c,v retrieving revision 1.19 diff -u -r1.19 main.c --- main.c 9 Dec 2004 14:07:59 - 1.19 +++ main.c 8 Mar 2005 16:40:50 - @@ -1,8 +1,9 @@ /* - * QD Uninstaller (main.c) + * Uninstaller * * Copyright 2000 Andreas Mohr [EMAIL PROTECTED] * Copyright 2004 Hannu Valtonen [EMAIL PROTECTED] + * Copyright 2005 Jonathan Ernst [EMAIL PROTECTED] * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,104 +19,94 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * ToDo: - * - add search box for locating entries quickly */ - #include stdlib.h #include stdio.h #include string.h -#include time.h -#include windows.h -#include main.h +#include windows.h +#include resource.h #include regstr.h +#include wine/unicode.h #include wine/debug.h -WINE_DEFAULT_DEBUG_CHANNEL(uninstaller); - -/* Work around a Wine bug which defines handles as UINT rather than LPVOID */ -#ifdef WINE_STRICT -#define NULL_HANDLE NULL -#else -#define NULL_HANDLE 0 -#endif - -/* use multi-select listbox */ -#undef USE_MULTIPLESEL - -/* Delete uninstall registry key after execution. - * This is probably a bad idea, because it's the - * uninstall program that is supposed to do that. - */ -#undef DEL_REG_KEY - -char appname[18]; -static char about_string[] = -Wine Application Uninstaller (C) 2004 by Andreas Mohr [EMAIL PROTECTED] and Hannu Valtonen [EMAIL PROTECTED]; -static char program_description[] = - Please select the application you wish to uninstall:; +WINE_DEFAULT_DEBUG_CHANNEL(uninstaller); typedef struct { -char *key; +WCHAR *key; WCHAR *descr; -char *command; +WCHAR *command; int active; } uninst_entry; +static uninst_entry *entries = NULL; +static unsigned int numentries = 0; +static int list_need_update = 1; +static int oldsel = -1; +static WCHAR *sFilter; +static WCHAR sAppName[MAX_STRING_LEN]; +static WCHAR sAboutTitle[MAX_STRING_LEN]; +static WCHAR sAbout[MAX_STRING_LEN]; +static WCHAR sRegistryKeyNotAvailable[MAX_STRING_LEN]; +static WCHAR sUninstallFailed[MAX_STRING_LEN]; + +static int FetchUninstallInformation(void); +static void UninstallProgram(void); +static void UpdateList(HWND hList); +static int cmp_by_name(const void *a, const void *b); +static WCHAR *stristr(const WCHAR *String, const WCHAR *Pattern); + + +static const WCHAR BackSlashW[] = { '\\', 0 }; +static const WCHAR DisplayNameW[] = {'D','i','s','p','l','a','y','N','a','m','e',0}; +static const WCHAR PathUninistallW[] = { +'S','o','f','t','w','a','r','e','\\', +'M','i','c','r','o','s','o','f','t','\\', +'W','i','n','d','o','w','s','\\', +'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', +'U','n','i','n','s','t','a','l','l',0 }; +static const WCHAR UninstallCommandlineW[] = {'U','n','i','n','s','t','a','l','l','S','t','r','i','n','g',0}; -uninst_entry *entries = NULL; - -unsigned int numentries = 0; -int list_need_update = 1; -int oldsel = -1; - -struct { -DWORD style; -LPCSTR text; -HWND hwnd; -} button[] = -{ -{ BS_PUSHBUTTON, Add/Remove, 0 }, -{ BS_PUSHBUTTON, About, 0 }, -{ BS_PUSHBUTTON, Exit, 0 } -}; - -#define NUM (sizeof(button)/sizeof(button[0])) - -int FetchUninstallInformation(void); -void UninstallProgram(void
Re: New uninstaller
Jonathan Ernst [EMAIL PROTECTED] wrote: Thanks for the hint. I found the allocation problem. Here is another one: +int len = GetWindowTextLengthW(GetDlgItem(hwnd, IDC_FILTER)); +if(len 0) +{ +sFilter = (WCHAR*)GlobalAlloc(GPTR, len + 1); +GetDlgItemTextW(hwnd, IDC_FILTER, sFilter, len + 1); And this one: +/* Load MessageBox's strings */ +LoadStringW(hInst, IDS_APPNAME, sAppName, sizeof(sAppName)); +LoadStringW(hInst, IDS_ABOUTTITLE, sAboutTitle, sizeof(sAboutTitle)); +LoadStringW(hInst, IDS_ABOUT, sAbout, sizeof(sAbout)); +LoadStringW(hInst, IDS_REGISTRYKEYNOTAVAILABLE, sRegistryKeyNotAvailable, sizeof(sRegistryKeyNotAvailable)); +LoadStringW(hInst, IDS_UNINSTALLFAILED, sUninstallFailed, sizeof(sUninstallFailed)); LoadStringW takes number of WCHARs, not bytes. Everything else seems to be good enough. P.S. Do I really have to split this new uninstaller in different patches as nearly everything changed ? It's up to Alexandre to decide, just send your work to wine-patches. -- Dmitry.
Re: New uninstaller
P.S. Do I really have to split this new uninstaller in different patches as nearly everything changed ? It's up to Alexandre to decide, just send your work to wine-patches. I would suggest that you do split it into seperate patches. If one of your patches causes a regression, it's easier to find the regression if the changes are small. Secondly, it's easier to review and verify small patches. Thirdly, since small patches are easier to check, they're easier to get accepted. How about creating three seperate patches that: 1. Change to use a dialog 2. Change to use unicode 3. internationalize the code This seems slower, but it will actually be faster, since you'll only need to perfect one patch at a time. Mike
Re: New uninstaller
Jonathan Ernst wrote: Here is the new uninstaller. I'll be away all this week so I send it already as it works well here (no regressions found) and has already some more features than the current one (so Iguess it can be safely committed, but I might be wrong of course). With some help I'll be able to improve it (more unicodification, etc.) when I'll come back. Changelog: - new uninstaller - find as you type search - use dialog instead of window - internationalization - more unicodification - if the uninstaller cannot be found the user can choose to remove the entry from the registry Hi Jonathan, You'll have more success getting this applied if you send each step as a seperate patch. I suggest starting by sending a single patch that converts the uninstaller to use a dialog instead of a window, adds a dialog resource in English and does nothing else. Once that patch is accepted, move onto the other tasks you have listed above. One step at a time makes the patch easier to review, and reduces the chance that a single line mistake will stop your entire patch from going in. Additionally, there's no need to change the name of main.c to uninstaller.c, that will just make it harder to see what has changed between versions. Mike
Re: New uninstaller
Jonathan Ernst [EMAIL PROTECTED] wrote: It's better to avoid using string tables, since now you have converted code to use dialog box instead. How can I do it for messageboxes ? Is there a way to define them in the resource files or do I have to make a dialog instead of messageboxes ? Yes, one of the possibilities to use dialog boxes instead of message boxes. But if it's inconvenient for you, then using string tables and LoadString is the only option. -- Dmitry.
Re: New uninstaller
Here is a new version. I'm thinking to send it as is to wine-patches if nobody complains before tonight (tomorrow I'll be leaving for one week). Thanks everyone for your help. Changelog: - new uninstaller - find as you type search - use dialog instead of window - internationalization - if the uninstaller cannot be found the user can choose to remove the entry from the registry --- /dev/null 2005-02-27 10:25:27.710808616 +0100 +++ uninstaller.c 2005-02-27 11:55:05.0 +0100 @@ -0,0 +1,423 @@ +/* + * Uninstaller + * + * Copyright 2000 Andreas Mohr [EMAIL PROTECTED] + * Copyright 2004 Hannu Valtonen [EMAIL PROTECTED] + * Copyright 2005 Jonathan Ernst [EMAIL PROTECTED] + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include stdlib.h +#include stdio.h +#include string.h +#include windows.h +#include resource.h +#include regstr.h +#include wine/debug.h + +WINE_DEFAULT_DEBUG_CHANNEL(uninstaller); + +typedef struct { +char *key; +WCHAR *descr; +char *command; +int active; +} uninst_entry; +uninst_entry *entries = NULL; +unsigned int numentries = 0; +int list_need_update = 1; +int oldsel = -1; +int FetchUninstallInformation(void); +char *sFilter; +WCHAR sAppName[MAX_STRING_LEN]; +WCHAR sAboutTitle[MAX_STRING_LEN]; +WCHAR sAbout[MAX_STRING_LEN]; +WCHAR sRegistryKeyNotAvailable[MAX_STRING_LEN]; +WCHAR sUninstallFailed[MAX_STRING_LEN]; + +void UninstallProgram(void); +void UpdateList(HWND hList); +int cmp_by_name(const void *a, const void *b); +char *stristr(const char *String, const char *Pattern); + +/** + * Used to output program list when used with --list + */ +void ListUninstallPrograms(void) +{ +unsigned int i; +int len; +char *descr; + +if (! FetchUninstallInformation()) +return; + +for (i=0; i numentries; i++) +{ +len = WideCharToMultiByte(CP_UNIXCP, 0, entries[i].descr, -1, NULL, 0, NULL, NULL); +descr = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); +WideCharToMultiByte(CP_UNIXCP, 0, entries[i].descr, -1, descr, len, NULL, NULL); +printf(%s|||%s\n, entries[i].key, descr); +HeapFree(GetProcessHeap(), 0, descr); +} +} + + +void RemoveSpecificProgram(char *name) +{ +unsigned int i; + +if (! FetchUninstallInformation()) +return; + +for (i=0; i numentries; i++) +{ +if (strcmp(entries[i].key, name) == 0) +{ +entries[i].active++; +break; +} +} + +if (i numentries) +UninstallProgram(); +else +{ +fprintf(stderr, Error: could not match application [%s]\n, name); +} +} + + +/** + * Fetch informations from the uninstall key. + */ +int FetchUninstallInformation(void) +{ +HKEY hkeyUninst, hkeyApp; +int i; +DWORD sizeOfSubKeyName, displen, uninstlen; +char subKeyName[256]; +char key_app[1024]; +char *p; + +numentries = 0; +oldsel = -1; +if ( RegOpenKeyExA(HKEY_LOCAL_MACHINE, REGSTR_PATH_UNINSTALL, + 0, KEY_READ, hkeyUninst) != ERROR_SUCCESS ) +{ + MessageBox(0, sRegistryKeyNotAvailable, sAppName, MB_OK); + return 0; +} + +if (!entries) + entries = HeapAlloc(GetProcessHeap(), 0, sizeof(uninst_entry)); + +strcpy(key_app, REGSTR_PATH_UNINSTALL); +strcat(key_app, \\); +p = key_app+strlen(REGSTR_PATH_UNINSTALL)+1; + +sizeOfSubKeyName = 255; +for ( i=0; + RegEnumKeyExA( hkeyUninst, i, subKeyName, sizeOfSubKeyName, + NULL, NULL, NULL, NULL ) != ERROR_NO_MORE_ITEMS; + ++i ) +{ + static const WCHAR DisplayNameW[] = {'D','i','s','p','l','a','y','N','a','m','e',0}; + + strcpy(p, subKeyName); + RegOpenKeyExA(HKEY_LOCAL_MACHINE, key_app, 0, KEY_READ, hkeyApp); + + if ( (RegQueryValueExW(hkeyApp, DisplayNameW, + 0, 0, NULL, displen) == ERROR_SUCCESS) + (RegQueryValueExA(hkeyApp, REGSTR_VAL_UNINSTALLER_COMMANDLINE, + 0, 0, NULL, uninstlen) == ERROR_SUCCESS) ) + { + numentries++; + entries = HeapReAlloc(GetProcessHeap(), 0, entries, numentries*sizeof(uninst_entry)); + entries[numentries-1].key = + HeapAlloc(GetProcessHeap(), 0, strlen(subKeyName)+1); + strcpy(entries[numentries-1].key, subKeyName); + entries[numentries-1].descr = + HeapAlloc(GetProcessHeap(), 0, displen); + RegQueryValueExW
Re: New uninstaller
Jonathan Ernst [EMAIL PROTECTED] wrote: With some help I'll be able to improve it (more unicodification, etc.) when I'll come back. You can't really convert to unicode partially, you have to do it in one go. That not only will simplify things a lot, but also will save you a lot of time. +for (i=0; i numentries; i++) +{ +len = WideCharToMultiByte(CP_UNIXCP, 0, entries[i].descr, -1, NULL, 0, NULL, NULL); +descr = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); +WideCharToMultiByte(CP_UNIXCP, 0, entries[i].descr, -1, descr, len, NULL, NULL); +printf(%s|||%s\n, entries[i].key, descr); There is no need to allocate len * sizeof(WCHAR) bytes, len works just fine. +int wmain(int argc, char *argv[]) wmain takes 'WCHAR *argv[]' list. All remaining problems are caused by the fact that now argv[] array is passed in unicode but you still handle argv[] strings as ASCII and pass them around to internal functions which accept 'char *' not 'WCHAR *' strings. -- Dmitry.
Re: New uninstaller
Le samedi 26 fvrier 2005 09:49 +0900, Mike McCormack a crit : [...] Cool. Some comments: The dialog box procedure should not handle WM_PAINT or WM_CLOSE, so just delete those cases from the switch statement. Ok I did it, but the listbox should be updated when the user ask to uninstall someting OR the user changes the filter string ? How can I do that using only WM_INITDIALOG ? Don't send WM_SETFONT messages to the controls in the dialog. Let the dialog template define what the dialog looks like. I removed it. Your WM_INITDIALOG handler should fill the listbox, not WM_PAINT. See my first question. You can remove the No items selected message if uninstall is clicked without a listbox element select. That's just going to annoy people, and it's not internationalized. I removed it. Internationalizaton will come after everything is alright. Thanks. P.S. Ivan Leo Puti I don't know if it'll be better to use WinMain. Using WinMain will make me to parse the command line manually isn't it ? uninstaller2.tar.gz Description: application/compressed-tar signature.asc Description: Ceci est une partie de message =?ISO-8859-1?Q?num=E9riquement?= =?ISO-8859-1?Q?_sign=E9e?=
Re: New uninstaller
Le samedi 26 fvrier 2005 12:09 +0800, Dmitry Timoshkov a crit : [...] 3) Stringtables a)Is there a way to load localized strings without having to guess beforehand the size of the string in each language ? b)Is there a way to not call LoadString for each string ? c)Where is the best place to load every string of a stringtable ? in main(), just before calling DialogBox() ? It's better to void using string tables, since now you have converted code to use dialog box instead. How can I do it for messageboxes ? Is there a way to define them in the resource files or do I have to make a dialog instead of messageboxes ? Thanks everyone for your comments, I'll send an updated version soon. signature.asc Description: Ceci est une partie de message =?ISO-8859-1?Q?num=E9riquement?= =?ISO-8859-1?Q?_sign=E9e?=
New uninstaller
As requested, I'm trying to make a new uninstaller using a dialog instead of a window. It's my first windows program and I have something working but there are still some issues. If someone could help with some of the following problems, I'd be very thanfull. 1) Strange problem with UpdateWindow uninstaller.c, line 264 I implemented a search/filter field and I want to repaint the window after each input in the EDITTEXT control. However, when I call UpdateWindow on this line, the value returned is 1 so that a WM_PAINT message should be sent right ? But strangly no message is sent and I have to make something else (like moving the dialog) to force the window to repaint and filter the entries. The funny thing is that UpdateWindow on line 279 works just fine. I guess it's a bug in my code and not in Wine so I'd be glad if you could help me. 2) Improve filter code Currently I filter the entries that match exactly the filter string. I would like to at least make a case insensitive strstr on the string. What's the best way to do it (See uninstaller.c, line 235) 3) Stringtables a)Is there a way to load localized strings without having to guess beforehand the size of the string in each language ? b)Is there a way to not call LoadString for each string ? c)Where is the best place to load every string of a stringtable ? in main(), just before calling DialogBox() ? 4) Please tell me if you see things that are bad in the attached code, so that I'll fix it before submitting a patch. Thanks you for your help uninstaller2.tar.gz Description: application/compressed-tar signature.asc Description: Ceci est une partie de message =?ISO-8859-1?Q?num=E9riquement?= =?ISO-8859-1?Q?_sign=E9e?=
Re: New uninstaller
Jonathan Ernst wrote: 4) Please tell me if you see things that are bad in the attached code, so that I'll fix it before submitting a patch. I think you probably want to pass a valid HINSTANCE to DialogBox, to do this you should start your program with WinMain() instead of main(). Ivan.
Re: New uninstaller
Jonathan Ernst wrote: As requested, I'm trying to make a new uninstaller using a dialog instead of a window. It's my first windows program and I have something working but there are still some issues. If someone could help with some of the following problems, I'd be very thanfull. Cool. Some comments: The dialog box procedure should not handle WM_PAINT or WM_CLOSE, so just delete those cases from the switch statement. Don't send WM_SETFONT messages to the controls in the dialog. Let the dialog template define what the dialog looks like. Your WM_INITDIALOG handler should fill the listbox, not WM_PAINT. You can remove the No items selected message if uninstall is clicked without a listbox element select. That's just going to annoy people, and it's not internationalized. Mike
Re: New uninstaller
Ivan Leo Puoti [EMAIL PROTECTED] wrote: Jonathan Ernst wrote: 4) Please tell me if you see things that are bad in the attached code, so that I'll fix it before submitting a patch. I think you probably want to pass a valid HINSTANCE to DialogBox, to do this you should start your program with WinMain() instead of main(). main() works just fine. GetModuleHandle(0) returns current HINSTANCE. -- Dmitry.
Re: New uninstaller
Jonathan Ernst [EMAIL PROTECTED] wrote: 1) Strange problem with UpdateWindow uninstaller.c, line 264 I implemented a search/filter field and I want to repaint the window after each input in the EDITTEXT control. However, when I call UpdateWindow on this line, the value returned is 1 so that a WM_PAINT message should be sent right ? No. UpdateWindow only sends WM_PAINT if there are invalidated areas to repaint. You need to use InvalidateRect first. Are you sure you want to repaint the whole window on each EN_CHANGE and not some small area of a dialog? But strangly no message is sent and I have to make something else (like moving the dialog) to force the window to repaint and filter the entries. The funny thing is that UpdateWindow on line 279 works just fine. I guess it's a bug in my code and not in Wine so I'd be glad if you could help me. 2) Improve filter code Currently I filter the entries that match exactly the filter string. I would like to at least make a case insensitive strstr on the string. What's the best way to do it (See uninstaller.c, line 235) Just send LB_FINDSTRING or LB_FINDSTRINGEXACT to listbox, it will do the job for you. 3) Stringtables a)Is there a way to load localized strings without having to guess beforehand the size of the string in each language ? b)Is there a way to not call LoadString for each string ? c)Where is the best place to load every string of a stringtable ? in main(), just before calling DialogBox() ? It's better to void using string tables, since now you have converted code to use dialog box instead. 4) Please tell me if you see things that are bad in the attached code, so that I'll fix it before submitting a patch. +BOOL CALLBACK DlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) BOOL - INT_PTR WM_PAINT is not needed for dialog boxes, user32 does the job. +int main(int argc, char *argv[]) +{ +MSG msg; +WNDCLASS wc; +HWND hWnd; +LPSTR token = NULL; +int i = 1; +HINSTANCE hInst = NULL; HINSTANCE hInst = GetModuleHandle(0); -- Dmitry.
Re: New uninstaller
Jonathan Ernst wrote: Ok I did it, but the listbox should be updated when the user ask to uninstall someting OR the user changes the filter string ? How can I do that using only WM_INITDIALOG ? You can get notifications from the controls that things change. For example, the edit control will send a WM_COMMAND( EN_CHANGE ) when the contents change. WM_INITDIALOG is just for setting things up. So create a function like fill_combo_box(), and call it whenever you need to update the combo box... when handling WM_COMMAND( EN_CHANGE ), WM_INITDIALOG, etc. Mike