Jump to content

I want to make a Notepad alternative in C


Recommended Posts

  • 2 weeks later...

I'm using RICHED20.DLL now. I snagged it from the Microsoft Installer 2.0 update package. This does fix the problem. It also gives me multiple undo capability and Unicode.

MSDN says that if I use the control in Unicode mode, it will expect Unicode messages. What does this mean? Can someone shed some light on this?

EDIT: What it actually says: "In Rich Edit 2.0, if you create a Unicode rich edit control (one that expects Unicode text messages), you must specify only Unicode data in any window messages sent to the control."

Edited by BenoitRen
Link to comment
Share on other sites

I *think* you should use SendMessageW and PostMessageW for all messages containing or retreiving stringdata, and use the widestring variant of the structs.

SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM) L"Text" );
wchar_t buffer[ 32 ];
SendMessageW( hwnd, WM_GETTEXT, 32, (LPARAM)buffer );
FINDTEXTW ft = { ... };
SendMessageW( hwnd, EM_FINDTEXT, FR_DOWN, (LPARAM) &ft );

Link to comment
Share on other sites

I just tried to find how to convert an ANSI string to a UTF-8 string, and there's no place that gives a clear answer in code. The closest I found was on CodeProject, and that was to represent UTF-8 in only the first 128 ASCII characters.

I'd have to find out how to detect a UTF-8 encoded file upon opening, too.

All this Unicode stuff is doing my head in. :(

EDIT: You have to do MultibyteToWideChar and then WideCharToMultibyte. However, encoding to UTF-8 is only supported on Windows 98 and later, unless I use the Microsoft Layer For Unicode. I give up, unless someone has a work-around. :(

Edited by BenoitRen
Link to comment
Share on other sites

Now I have a different problem. :(

I want to disable the Save menu item when no changes have been made. First I tried to use EnableWindow for this purpose. That didn't work. So I did a Google search, and found that I needed to use EnableMenuItem. I used it like described on the page and in Borland's reference, and came up with this:

EnableMenuItem(GetMenu(hwnd), ID_FILE_SAVE, MF_GRAYED);

However, it still doesn't work! What am I doing wrong?

By the way, since switching to Rich Edit Control 2.0, search is done backwards, with only one result found each time. What the hell is this?!

EDIT: And now the menu item graying works fine. Did I forget to compile, or something? :/ EDIT: Indeed. I caught myself running my program after making changes without compiling first.

Edited by BenoitRen
Link to comment
Share on other sites

Have a look here:http://en.wikipedia.org/wiki/UTF-8#Description

UTF-8 uses 1,2,3 or 4 bytes a character depending on the numerical value of the (unicode) character. When saving a file in UTF-8, notepad will add a header 0xEF 0xBB 0xBF. A file starting with this sequence you can consider UTF-8 encoded. Another file *might* be UTF-8 encoded too, but there's no way to be be sure. Read this

Ansi is a 'strange' standard (actually it isn't a standard), so the best way to convert Ansi to UTF-8 is converting it to unicode with MultibyteToWideChar, and then convert this to UTF-8.

Link to comment
Share on other sites

When I replaced the RICHED20.DLL file I had by a more recent one, the search bug went away. But now it's back again!

I've been trying, in vain, to make my program open a file specified at the command line. Here's what I've done to achieve that. In my WinMain I have:

if (*lpCmdLine != NULL) strcpy(g_szFileName, lpCmdLine);

If there's something in the command line, it gets copied into my global variable that holds the path to the opened file. It's defined near the top of my source as follows:

char g_szFileName[MAX_PATH] = "";

This seems to work, as when I show the variable's contents using a MessageBox, I get what I inputted at the command line. Next, in my window process' WM_CREATE event, I do:

if (*g_szFileName != NULL) {
if (loadFile(g_szFileName) == TRUE) SetWindowText(hwnd, strcat(g_szFileName, " - Kladblok"));
else MessageBox(hwnd, "Er was een fout tijdens het openen van het bestand.", "Fout", MB_ICONEXCLAMATION | MB_OK);;
}

But this doesn't work. For some reason when my program gets here g_szFileName is empty! I verified with a MessageBox.

Link to comment
Share on other sites

By the way, since switching to Rich Edit Control 2.0, search is done backwards, with only one result found each time. What the hell is this?!
There is a difference between v1 and v2: http://msdn.microsoft.com/en-us/library/bb788009(VS.85).aspx. Did that bite you?
For some reason when my program gets here g_szFileName is empty!
Then it's overwritten or hidden by another variable. Did you declare some array directly before or after g_szFileName? Check if you don't exceed their bounds. You don't have a debugger, I suppose?
Link to comment
Share on other sites

Thanks, that difference did bite me. What a nasty default behaviour.

I wouldn't know how I'm exceeding any bounds. The char array I have is definitely big enough. Here's my source code if you have time to look into it. I do have the Turbo Debugger, but I can't figure out how to work with it.

Link to comment
Share on other sites

IIRC, CreateWindow calls WndProc with WM_CREATE before returning.

Also, if you create your RichEdit text box with CreateWindow(Ex)W, then it's a Unicode text box. Create it with CreateWindow(Ex)A, then it's non-Unicode. There's really no reason you should be using non-Unicode in this day and age. All the APIs in WinNT are natively Unicode, so you are incurring extra thunking costs every time you use one of those outdated "A" APIs.

Link to comment
Share on other sites

Then it's overwritten or hidden by another variable.
I forgot the 3rth possibility. It's not yet filled. You read g_szFileName in WM_CREATE, which is called inside CreateWindowEx() in WinMain(). g_szFileName is filled after this.

FYI, I didn't see this directly, so I did some debugging-without-debugger magic. I exchanged 

char *g_szFileName[MAX_PATH] = "";

by

#define _DEBUG
#ifdef _DEBUG
char *fun_szFileName(int line)
{
 static char _szFileName[MAX_PATH] = "";
 char buf[ 16 ];
 MessageBox( 0, itoa( line, buf, 10 ), "szFileName", MB_OK );
 return szFileName;
}
#define g_szFileName fun_szFileName(__LINE__)
#else
char *g_szFileName[MAX_PATH] = "";
#endif

Now it's easy to see when and from where g_szFileName is accessed. For more complex problems you'd better use a logfile instead of a messagebox.

Link to comment
Share on other sites

Now I'm very confused. Text replacing doesn't work anymore. It does work with RichEdit version 1, but the CHARRANGE members have the same values.

This is my replace function:

int replaceText(char *findWhat, char *replaceWith, BOOL bWholeWord, BOOL bMatchCase, BOOL bSearchDown) {
CHARRANGE cr;
int foundText = 0;
SendMessage(g_hRichEdit, EM_EXGETSEL, 0, (LPARAM) &cr);
if (cr.cpMin == cr.cpMax) foundText = searchText(findWhat, bWholeWord, bMatchCase, bSearchDown);
else {
CHARRANGE crText;
FINDTEXTEX ftex;
ftex.chrg = cr;
ftex.chrgText = crText;
ftex.lpstrText = findWhat;
SendMessage(g_hRichEdit, EM_FINDTEXTEX, 0, (LPARAM) &ftex);
if (ftex.chrgText.cpMin == cr.cpMin && ftex.chrgText.cpMax == cr.cpMax) {
MessageBox(NULL, "About to replace!", "Kladblok", MB_OK);
SendMessage(g_hRichEdit, EM_REPLACESEL, TRUE, (LPARAM) replaceWith);
}
foundText = searchText(findWhat, bWholeWord, bMatchCase, bSearchDown);
}
return foundText;
}

The idea is that if nothing is selected, a search is made for the text so that the next time the function is called it will be selected. To be on the safe side, I do a search for the text within the selection to verify that it is indeed the string I want to replace. If that's the case, the CHARRANGE of the current selection and the one that has the search results should be the same.

However, in practice, in both versions of the RichEdit control, cpMin of the selection is always lower by 2 (in my testcase of trying to replace 2 characters) than cpMin of the search result. The cpMax values are very high numbers. The strange thing is that with version 1 the replacement happens, but not with version 2, even though the values are the same and the condition should always be false. What's going on?

Edited by BenoitRen
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...