Duoas 1,025 Postaholic Featured Poster

Listen, I'm not making this stuff up.

Here's the official Microsoft Documentation.

At the end of the page here it says that you need at least Windows 95 or NT 3.1 (both the basic Win32 platforms). I've used hook procedures on XP, and they are still valid in Vista.

If you want to capture input when you application is not active, you have only two choices: use SetWindowsHookEx(), or hack the kernel.

Now please go and try to do it before complaining that it won't work. And remember, if you want a system-wide hook, you will need to put your hook callback in a DLL.

Duoas 1,025 Postaholic Featured Poster

How do you figure? SetWindowsHookEx() is a Win32 function, and is supported on every Windows OS since.

Duoas 1,025 Postaholic Featured Poster

You mean another different question? ;) (Kind of like "Can I ask a question?" heh heh heh...)

I don't mind personally, but I'm not sure what the convention is here...

Duoas 1,025 Postaholic Featured Poster

You'll have to look at the documentation for SetWindowsHookEx(). The hook type you want is WH_KEYBOARD, if you intend it intercept and maybe change the keyboard input, or WH_JOURNALRECORD just to monitor it.

You can google all of this over at MSDN.

Good luck.

Duoas 1,025 Postaholic Featured Poster

char string[80]; only creates an array of 80 characters. The array is named "string".

There is a problem with the order in which you are doing things. You get another string from the user before you copy "bill" to the "string" array.

The weird character is because you did not initialize your "string" array properly. You are lucky the program didn't crash.

Somewhere at the top, say line 11 or so, say string[0] = '\0'; Hope this helps. :)

PS. Don't name arrays "string" either. Come up with a real name.

[EDIT] Oh yeah, strcat_s() is non-standard MS crap. If you are only going to use the MS compiler, then fine, else stick with strcat().

Duoas 1,025 Postaholic Featured Poster

The stuff on the net should generally work just fine. You might have troubles using components written for D3 or earlier, but most of the stuff I've seen out there are good for at least D4.

A DPK file is how people usually distribute stuff for Delphi. In the help documentation search for a page titled "About Packages". It will tell you all about packages and how to use them.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

You'll need a temporary string (ASCIIZ) at least 260 bytes long (260 is a Windows thing). First copy the directory name to the string. Then concatenate a "\", then concatenate the filename. Use the temporary to name the file in your copy/open function.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

Did you just give up or did AD's suggestion help solve your problem?

I've had occasion to arrange an array of pointers to string just like you are, which is fine, but without a better idea of what you are trying to do with all the indirection it is hard to help you.

Duoas 1,025 Postaholic Featured Poster

You misunderstand something about pointers.

"temp" is an array of 80 characters. There is now space reserved in memory for 80 characters. The name "temp" by itself is a pointer to the first character in the array.

"array" is an array of 255 pointers to characters. There is now space reserved in memory for 255 pointers (not characters). The name "array" by itself is a pointer to the first pointer in the array. (BTW, don't name things "array".)

So, if you say strcpy( temp, "Hello" ); then the temp[] array contains the string "Hello".
If you then say strcpy( temp, "world" ); then the temp[] array contains the string "world". The string "Hello" is overwritten, and no longer exists.

In your loop, you assign array[ n ] (a pointer to a character) the address of the first char in the temp array. So,

strcpy( temp, "Hello" );  // temp[] contains "Hello"
array[ 0 ] = temp;
// array[ 0 ] points to "Hello" in temp[]

strcpy( temp, "world" );  // temp[] contains "world"
// array[ 0 ] still points to temp[], but temp[] now
// contains "world"

Your loop is failing because "i" starts at one when it should start at zero. In other words, when you increment "i" you are saying that there is one more item in the "array" than there really is.

Hope this helps.

[EDIT] You know, it really is difficult to help when you change things after …

Duoas 1,025 Postaholic Featured Poster

You are looking at a not-so-great attempt at creating an application mutex. There is no OS support for such a thing in *nix, so the traditional way to do it is to create a "lock file", hence the flags (particlularly O_EXCL, or 'exclusive access').

A better algorithm is here, as it can withstand program crashes --it doesn't need to clean up after itself.

There is also "gtkunique" (google it), a small library that does nice stuff for you.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

Destructively or non-destructively?

Why do you have so much indirection?

Duoas 1,025 Postaholic Featured Poster

What is the "7" for when you call the function in main()? Just call it without the "7". (I don't know why it complained about (..., int n), as that should have made the compiler change its complaint to "argument 'n' not used in function bubbleSort()".)

You might want to read up a little on templates. Here's the reading at the C++ FAQ Lite. There is a difference between a template class and a template function.

However, since your sort only works on miniVectors, it might be a good idea to make the sort function a member of the miniVector template class template <typename T> void miniVector<T>::bubbleSort() It really is a selection sort. A selection sort looks ahead for the smallest next element. A bubble sort only concerns itself with adjacent elements. The Wikipedia generally has good articles on such things.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

Even experienced people are a little intimidated when they see a lot of class code or the like. It isn't a simple question. You are asking for someone to take a little while to completely analyze your code, rather than deal with a specific question.

Your bubble sort looks fine from just glancing over it, but what is that int[] argument? It has no name and is not used.

Did you try compiling this? Did you try using it? Do those things and you'll get some instant feedback on exactly what works and what doesn't.

Good luck.

[EDIT] Oh yeah, that bubbleSort( int&, int ) makes no sense. A single integer is always sorted. If it were bubbleSort( int[], int ) then I would venture that your teacher wants you to write it without the template, then convert it to a template: bubbleSort( miniVector<T> & ).

Duoas 1,025 Postaholic Featured Poster

No. A window must be visibe to be active (i.e. in order to receive user input events).

Even though the window is inactive, your application is still running though, and can receive other events.

You can set a system hook to capture events you are interested in, using SetWindowsHookEx(). System-wide event hooks usually require a DLL.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

You may not like my saying, but those are pretty stupid restrictions. Your program is going to be pretty boring.

Is there some reason you don't want to use more than five lines?

Duoas 1,025 Postaholic Featured Poster

Your code is somewhat verbose, so it is a little difficult to follow...

I got as far as out2. You are shifting bits off the end of AX. I'm still not sure how you are getting your outputs. But, assuming that input_buffer contains four bytes each in the range 0..63:

; re-arrange bits into their proper slots
        mov     ax, input_buffer[ 0 ]  ; al,ah = [0],[1]
        shl     al, 2
        shr     ah, 4
        add     al, ah
        mov     output_buffer[ 0 ], al

        mov     ax, input_buffer[ 1 ]  ; al,ah = [1],[2]
        shl     al, 4
        shr     ah, 2
        add     al, ah
        mov     output_buffer[ 1 ], al

        mov     ax, input_buffer[ 2 ]  ; al,ah = [2],[3]
        shl     al, 6
        add     al, ah
        mov     output_buffer[ 2 ], al

Another error is converting '=' into spaces in the output. Don't. Just reduce the number of bytes you actually write to the output.

In other words, you would normally write 3 bytes to output. For each '=' decrement that by one:

; cx <-- number of bytes to write
        mov cx, 3
        mov ax, input_buffer[ 2 ]

        cmp al, '='
        jnz ok1
        dec cx

ok1:    cmp, ah, '='
        jnz ok2
        dec cx

        ; write cx bytes to file
ok2:    mov ah, 40h
        mov bx, output_handle
        lea dx, output_pointer
        int 21h

The x86 string opcodes are very powerful and very useful.
Here's something along the lines of C's strcmp():

; prereqs:
        push ds
        pop  es
        cld

        ; find index of char_to_find
        mov al, char_to_find
        mov …
Duoas 1,025 Postaholic Featured Poster

Ah, yes, that works.

Still, I would repeat myself instead of calling FormCreate again.

procedure TForm1.RedoFunctionButton(Sender: TObject);
begin
memo1.Lines.Text :=  GetNicAddr;
end;

Have fun!

squidd commented: This man's patience with me is super-human. +1
Duoas 1,025 Postaholic Featured Poster

Don't use a DATAGRAM protocol. Just open your socket using SOCK_STREAM or something that guarantees delivery.

Duoas 1,025 Postaholic Featured Poster

"When the program starts" is actually a little vague.

Which functions/procedures are being called when your program starts?

Are they being called in the main program file's begin..end. block?
Or in some unit's initialization section?
Or in some form's constructor? or FormCreate event?

Duoas 1,025 Postaholic Featured Poster

Well, I've been playing with it and I can't match your exact description. I presume you are using MIME encoding.

To preserve spacing, I'll continue in a code block:

"Man A" should encode as "TWFuIEE="
"Man   A" (with three spaces) encodes as "TWFuICAgQQ==".
Both decode for me correctly.

Now, if you are getting the first to encode as the second, then there is an error in your encoding algorithm.

If you are getting the second to decode with only two spaces, then there is an error in your decoding algorithm.

If you haven't figured out what it is yet, please post it and I'll take a look at it.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

I must have been really tired when last I posted because I thought that the beginning and end of this thread was two separate threads...

As per your original question, whatever you are doing in FormCreate that needs to be done again, just stick it in another, private method.

...

type
  TForm1 = class( TForm )
    ...
  private
    // Add yourself a method that does what you want
    procedure do_something;
  end;

...

// Define it
procedure TForm1.do_something;
  begin
  // does it here
  end;

...

procedure TForm1.FormCreate( sender: tObject );
  begin
  ...
  do_something;  // use it
  ...
  end;

procedure TForm1.fooButtonClick( sender: tObject );
  begin
  do_something;  // use it again
  ...
  end;

Your solution to just call FormCreate again is also OK, so long as FormCreate only does what you need done again. I would prefer to separate it out into a separate method just for logical consistency and to make you life easier should you later want to make FormCreate do something unrelated to clicking the button (as is wont to happen).

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

As this is C++, you should be parsing each record using a stringstream and getline(). Here's minimal code to get you started.

string record, field;
getline( cin, record );
{
  stringstream fields( record );
  for (
    int field_index = 0;
    getline( fields, field, '|' );
    field_index++
    )
    store_field( field_index, field );
}

The store_field() function takes an index and a string. Depending on what the indexed field should contain, the function should convert the string to it (use another stringstream for the conversion). If the string is empty, then use a default.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

Using the Win32 API, you need to:

1. CreateCompatibleDC to create a DC compatible with your window's DC
2. CreateCompatibleBitmap with the appropriate dimensions
3. SelectObject to select the window into the bitmap
4. BitBlt the window into the bitmap
5. Save the bitmap as Jpeg

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

I don't understand what you mean about spaces. Are you saying that spaces in your original file are producing spaces in your encoded file?

The encoded file will naturally contain spaces, but these are not part of the data, and should be ignored when decoding.

Duoas 1,025 Postaholic Featured Poster

And system() is very easy to subvert into doing something other than what you intended.

not necessarily if executed right the system() tag is very good but still best to avoid.

How exactly are you to guarantee that the user doesn't replace an external program from your code? The system() function does exactly what it is supposed to: execute an external program. Anytime you do that it is a security hole.

And no it will not create another process unless you tell it too.

Grumble... You are aware, perhaps, that the whole point of the system() function is to create another process?

It executes another copy of your system shell, which in turn may execute yet another process (or processes)...

Duoas 1,025 Postaholic Featured Poster

Originally, you had an integer, which we used as an index into a table of ASCII values. Basically, we said: output_char = ascii_values[ input_index ]; Now you want to go the other way --that is, convert the ASCII value into an index into the table. That's where scasb comes in. Put the length of your table in CX, the value you are looking for in AL (I think), and execute REP SCASB. When done, subtract the address of the beginning of the table from DI. Now DI == the original index into the table, or one too large if the character was not found in the table:

DX = DI - OFFSET ascii_values
if DX == 64 then not found
else DX is the original input value

Bit shift DX into the right place in the output and add it in. After four characters are converted into indices, and shifted into the 3-byte array, you can then output it.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

Well, if you are checking them all for validity at the same time, then sure, just put them together:

if (edit1.text = '')
or (edit2.text = '')
or (edit3.text = '')
 then MessageDlg('whatever goes here',mtWarning,[mbOK],0)

But it is better to separate them, so that you can visually indicate which one is in error:

...

type
  TForm1 = class( TForm )
    ...
  private
    // Add yourself a function that checks for errors
    function check_edit_error( sender: tEdit ): boolean;
  end;

...

// Define it
function TForm1.check_edit_error( sender: tEdit ): boolean;
  begin
  // Was there an error?
  result := sender.text = '';
  // Yes, complain
  if result then begin
    messageDlg( 'fooey', mtWarning, [mbOK], 0 );
    sender.setFocus
    end
  end;

...

procedure TForm1.fooButtonClick( sender: tObject );
  begin
  // Check all the edit boxes we need right now for error
  if check_edit_error( edit1 )
  or check_edit_error( edit3 )
    then exit;

  ...

  end;

Don't use mtError except for errors that are fatal or nearly fatal to your application. For something like this I would use mtWarning or mtInformation, since the program is simply explaining to the user that it cannot continue until proper input is given.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

Google "bignum C++".

Duoas 1,025 Postaholic Featured Poster

Just create a utility function to get the number. When your program starts, call the function. When you press the button, an event method (onClick) gets called. Inside Button1Click just call the function again.

Alas, for errors, it is usually simple enough just to write the messageBox( ... ) stuff over again. Borland compilers are very smart about optimizing strings, so you don't have to worry about bloating your code by the repetition.

However, if you know you'll use it the exact same way many, many times, you could just create a little method that calls the messageBox (or whatever the error message dialog function you are using is), then just call your method whenever the user error occurs.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

Was the help in this thread not good enough for you?

Duoas 1,025 Postaholic Featured Poster

You have only re-stated your original premise:
1. you are using C to write a graphics program
2. you want to convert an image from color to greyscale

My answer is:
1. C doesn't do graphics. Either you are using some sort of graphics library or you are writing your own. What graphics library are you using?

2. The best way to convert an image to greyscale depends entirely on (1).

3. Tell me also if your program is for Windows, or Linux, or cross-platform, or what.

Please answer my two questions and I will then be able to help you.

Duoas 1,025 Postaholic Featured Poster

How are you displaying your text? (Rich Edit? Something you made? Console?)

Duoas 1,025 Postaholic Featured Poster

Almost all the functions in the C library are useful in their domain (all except gets()!).

Use system() when you need to. There is nothing wrong with it.

However, how often do you need to execute shell commands from your program? The usefulness is pretty rare. The thing people get upset about is that system() gets used for all sorts of stuff it shouldn't be.

For example, it is cool that you can set the console window's title from the cmd prompt, but that is a Win32 thing. Instead of spawning a new shell and sending it a command which will likely fail on any system except Win 98+, just use the SetConsoleTitle() function, and let compilation fail if the program won't work on the target system. Make sense?

That's all I meant.

Duoas 1,025 Postaholic Featured Poster

Unfortunately, clearing the screen is impossible to do without platform specificity.

mugenoid, let us know what OS you are using and we'll give you a good solution.

Mr. Cool, unless you are running on hardware as old or older than an AT, it is just way too fast to make coding no-op loops useful. Even then, it is a bad idea, as the OS can do better for just pausing long enough for the user to read the screen...

Duoas 1,025 Postaholic Featured Poster

That's not really enough information for us to help you.

C++ (and C) don't do graphics. What libraries are you using? What do you mean by "image"? Stuff on disk? Something in memory?

ImageMagick is a good library solution if you don't already have something else going.

Duoas 1,025 Postaholic Featured Poster

Actually, I might have that backwards. Point is, if your system is configured correctly (and most are out of the box) then it won't matter which rich edit DLL you call.

[EDIT]

It is likely that the problem is not with the rich edit control but with the program using it. There is no way to directly set a character index on huge texts with the API. You can only do it relatively.

If the calling code is keeping track of the character index in an int or long or something that is too small, then it will wrap when too much is added to it.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

If you are doing a game, don't use system("cls"). Write it properly.

What OS are you using? Windows? Linux?

Duoas 1,025 Postaholic Featured Poster

Don't feel too bad. People post system() stuff all the time.

Other than using "cls" or "clear" in a homework assignment, there are always better ways to do things than by using system().

One of the main problems with it is it is a security hole in your program --even if you are not writing secure systems software.

Another is the overhead. Just to clear the screen or do some other simple thing it takes a relatively large amount of time and resources.

Duoas 1,025 Postaholic Featured Poster

Sorry to respond so late.

Your code to read things in should look something like this (remember: this is how to do it in your head):

function read_equation( var head: pEquation; var f: textFile ): boolean;
  var c: char;
  begin
  result := false;
  c := ' ';
  while not eoln( f ) do
    begin
    result := true;
    if is_digit( c )
      then add_new_number_node( head, read_digits( f, c ) )
      else
    if is_operator( c )
      then add_new_operator_node( head, read_operator( f, c ) )
      else
    if is_space( c )
      then skip_spaces( f, c )
    else begin
         writeln( 'Invalid equation at ''', c, '''' );
         result := false;
         break
         end
    end
  end;

You will, of course, have to define is_digit, is_operator, is_space, read_digits, read_operator, skip_spaces, add_new_number_node, and add_new_operator_node.

Also, make sure that your head points to an empty or nil equation each time before calling this function.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

The riched20.dll is just a wrapper for riched32.dll.

The rich edit defaults to a limit. Try sending it the following message: SendMessage(hwnd, EM_EXLIMITTEXT, 0, -1); Thereafter it shouldn't have limits.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

Great. When you are ready to go the other way, you can use rep scasb to look for an item in the table, and subtract the difference between the location of the item in the table and the beginning of the table to get the index of the item.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster
procedure TForm1.FormCreate( Sender: TObject );
  begin
  TrayIcon1.PopupMenu := PopupMenu1
  end;

This presumes you dropped a popup menu on your form and populated it with the menu designer.

Duoas 1,025 Postaholic Featured Poster

I'm not sure exactly what problems you are having, but the stuff following B4 has some errors.

First, if you only want to clear the top two bits of AL then shl al, [B]2[/B] shr al, 2 Or, even simpler: and al, 3Fh Also, you only add 61 to it instead of 65 as you did in all the others.

You are aware, I presume, that simply adding 'A' doesn't account for three things: punctuation characters between A..Z and a..z, a control character (ASCII 127), and the fact that you exceed the ASCII character range by one character (your domain is 65..128, while ASCII is only defined on 0..127).

You would do better to use a lookup table for ASCII digits and use the xlat instruction to convert AL.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

For others reading here:

If you know that your register is bit-formatted correctly for the coprocessor, use the mfc1 and mtc1 instructions. They are also in that link.

Glad to be of help.

Duoas 1,025 Postaholic Featured Poster

OK, I've glanced through the TTrayIcon component's code.

Just drop a TPopupMenu on your form, populate it as desired, then when your form creates assign it to the PopupMenu property of the TTrayIcon.

Glad to be of help.

Duoas 1,025 Postaholic Featured Poster

You are probably right, but make no assumption about how the monitors are arrayed. If you are right, the code will still properly center the form on the monitor (because application.monitors[ n ].top will be zero).

> I will inform you of whatever I find out.
Please do.

:)

Duoas 1,025 Postaholic Featured Poster

There's nothing wrong with saving a record directly to file like he does. All it means is that he only needs to dink with one thing at a time in the file instead of many. In fact, that's the whole point behind a record.

There are a number of organizational problems with your code, but as they aren't critical I won't bother you with them (unless you want).

The main feature of the assignment is that you are not supposed to load the file at any point: instead you are to only "view" a single record of the file at any given time.

Lets consider how a file of record looks:

[record 0][record 1][record 2][record 3]...

That is, it is a sequential list of records. To read or overwrite a specific record, just seek to the beginning of that record and read or write it.

So, the first thing you need is a way to seek out a specific record in the file, given its index. I suggest you make yourself a little function to do it, like: procedure indexEmployeeNumber( index: cardinal ); If the file is too short to have the 'index'ed record, just seek to the end of the file.

Next, your assignment asks you to keep track of which record you are currently viewing. That is, you must remember the index of the current record: 0, 1, 2, .... When you are asked to move to the previous or next record, adjust …

Duoas 1,025 Postaholic Featured Poster

You need the cvt.s.w and cvt.w.s instructions.

If you don't have a reference, here's a PDF for you: MIPS - Floating Point Instructions.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

You know what, TCustomForm.Monitor is read-only. Sorry about that.

I've googled about a little and it looks like Delphi doesn't specifically provide a way to do what you want with the VCL (because the Win32 API doesn't either).

You'll have to set the left, top position of your form so that it is in the area of the desired monitor. For example:

constructor TForm1.Create(Sender: TObject);
  begin
  // Center the form on the third monitor
  with application.monitors[ 2 ] do begin
    self.left := left +(width  div 2) -(self.width  div 2);
    self.top  := top  +(height div 2) -(self.height div 2)
    end
  end;

This code presupposes that there are at least three monitors attached... You'll want to choose a monitor more carefully than my hardcoded number.

Sorry for the mistake earlier. Unless there is something else going on that I don't know about this should work. Remember, I've no way to test it.

Good luck. Let me know what works.

Duoas 1,025 Postaholic Featured Poster

Ah, I have learned something. (Further proof that C99 is weird...)