Try it. :)
(Its a preprocessor macro.)
Try it. :)
(Its a preprocessor macro.)
Just change CC=gcc
to CC=g++
Behold, the Make Anything Makefile:
#-----------------------------------------------------------------------------
# Make Anything Makefile
#-----------------------------------------------------------------------------
# For use with GNU Make
#
# The only prerequisite to using this Makefile is that the program source
# files all reside in their own directory, with only ONE of these source
# files declaring main(). For example,
#
# my_last_nameHW3/
# Makefile <-- "make anything" makefile
# linked_list.h
# linked_list.cxx <-- the file the student modifies
# node.h
# test_linked_list.cxx <-- the file containing the main() function.
#
# This makefile will correctly identify the files and produce:
#
# linked_list.o
# test_linked_list.o
#
# and then the executable
#
# test_linked_list*
#
# The orphan "node.h" is included in every source module's prerequisites,
# regardless of whether it is actually used by that module.
#
#-----------------------------------------------------------------------------
# When MIXING C and C++ modules, this makefile will compile the C modules
# with the C compiler, and the C++ modules with the C++ compiler. Keep that
# in mind! (Also, the linking stage will be done with the C++ compiler.)
#
#-----------------------------------------------------------------------------
# "make clean" works as usual.
# "make cleaner" works better than usual.
#
# --Michael
#
#-----------------------------------------------------------------------------
# general options
#-----------------------------------------------------------------------------
# These are the names of the C and C++ compilers to use, and options common
# to both compilers.
#
# If you want to specify an option specific to only one of the compilers,
# just place it after the compiler name. For example: …
Good grief!
n.aggel, you had the right idea to begin with, only your syntax needs help. Don't change the definition of the function, but just pass the appropriate pointer.
void array_function(int rows, int cols, float after[rows][cols] , float before[rows][cols])
{
...
}
int main()
{
int n = 5;
int m = 6;
int before[n][m];
int after[n][m];
array_function( 5, 6, before, after ); // this works
array_function( 5, 6, after, before ); // this works
...
}
Hope this helps.
[edit]
Argh. Sorry about leaving out <limits>. (I forgot and GCC doesn't complain.)
I come from a Pascal background so I tend to like things you can actually read... I didn't know that VC++ doesn't understand and or or. (Stupid VC++.)
You should be very pleased with the results. The algorithm is very quick, and typically needs to examine only a very few lines before finding the answer.
I also forgot to mention earlier that lines that do not begin with a valid date of the form MM/DD/YYYY or MM-DD-YYYY are completely ignored, so it is OK if your file contains blank lines or other information.
Enjoy. Thanks a ton AD. You rock!
I don't know if you downloaded them correctly. They are plain-text files, not HTML or anything else. If you open them in notepad you shouldn't see anything funny.
Go to the download, click download. When you get the web page showing the file, select File --> Save Page As... and make sure the bottom-most drop-down box says the document type is "Text Document".
If you've done that (and I see that you put the include in the right spot), then you'll have to ask AD for more help. (Stupid MS VC++.)
Let me go dig out my old version of VC++ and see what weirdness it wants...
(Alas, I was looking forward to a happy you.)
guest7, you've already made several unseemly blunders, but now you are risking being completely ignored.
Please read up before becoming belligerent.
How To Ask Questions The Smart Way
That C code is a mess. And it is dangerous because it uses bitfields (which C++ does not guarantee to be packed in any specific order -- so results vary by compiler!).
Alas, why don't programmers stp usng stpd shrt nonsns nms.
Anyway:
uses
SysUtils, // for PByteArray
Winsock; // for htons()
const
IP_DF = $4000; // don't fragment flag
IP_MF = $2000; // more fragments flag
type
in_addr = record ... end; // you must fill this in
iphdr_ptr = ^iphdr;
iphdr = packed record
ip_hl__ip_v: byte; // header length, version: four bits each
ip_tos: byte; // type of service
ip_len: shortint; // total length
ip_id: word; // identification
ip_off: shortint; // fragment offset field
ip_ttl: byte; // time to live
ip_p: byte; // protocol
ip_sum: word; // checksum
ip_src: in_addr; // source address
ip_dst: in_addr // destination address
end;
procedure RecalculateIPChecksum( pIpHeader: iphdr_ptr );
var
sum: longword;
i: longword;
buff: PByteArray; // see note 1
begin
sum := 0;
i := 0;
// Initialize checksum to zero
pIpHeader^.ip_sum := 0;
buff := pIpHeader;
// Calculate IP header checksum
while i < (pIpHeader^.ip_hl__ip_v and $F) *sizeof( longword ) do // see note 2
begin
inc( sum, (buff[ i ] shl 8) +buff[ i +1 ] );
inc( i, 2 )
end;
// Keep only the last 16 bits of the 32 bit calculated sum and add the carries
while (sum shr 16) <> 0 do
sum := (sum and $FFFF) +(sum shr 16);
// Take the one's …
OK, sorry for the public service... (I also lost my webspace a short while back...)
Don't forget to read my comments in the last post.
Just copy the datefile files into your project folder and add them to your project.
Make sure to #include "datefile.hpp" in your program (in the files where you intend to use it).
Heh...
Alright! :)
Sorry for the delay. There were a few more corner cases than I thought there would be when I started this. But anyway, here you go. Hope you find it useful.
The algorithm presumes that the dates in your file are more or less linearly distributed. If this is not the case by more than a standard deviation, open "datefile.cpp" and comment out the line #define LINEAR_DISTRIBUTION
Sorry for the boilerplate, but companies get nervous without it. Basically it just says you can do anything you like with the files except claim anyone but I wrote the original versions or alter the boilerplate... (and excludes me from legal responsibility if someone manages to destroy something with it).
The file "a.cc" is what I used to test the datefile algorithm. You don't need it, but I've attached it anyway so you can play with it if you like. Its messy though...
Let me know if anything goes horribly wrong. ;)
So, here's a quick primer:
#include <iostream>
#include <fstream>
#include "datefile.hpp"
using namespace std;
using namespace datefile;
int main()
{
ifstream megafile( ... );
time_t date = string_to_date( "4/28/1974" );
streampos linepos = find_date( megafile, date );
if (megafile) // or (!megafile.eof())
{
string line;
getline( megafile.seekg( linepos ), line );
cout << "Found the line> " << line << endl;
}
else
{
megafile.clear();
cout << "No such date found.\n";
}
...
megafile.close();
return 0;
}
Enjoy! :)
Hmm. …
Text mode is good (makes things simpler).
Give me just a little longer to finish testing all the various corner cases where things can go wrong.
Actually, you got me interested, so I'm writing a little library for you to do it... :)
My method accounts for the possibility that lines are different lengths.
As a matter of interest, do you open the file in textual or binary mode?
If you know something about the distribution of dates in the file you can get the fastest time, but in any case you'll have to do a random-access search.
This should help, but may not if the date is in a worst-case position:
Hope this helps.
The problem is exactly what it is saying.
For example, you have a procedure prototyped as: [B]void[/B] GetTemperatures ([B]int[/B] Temperatures[], [B]int[/B] NumTemperatures);
...which clearly states that it requires two arguments.
but in main() you don't specify any arguments: GetTemperatures ();
You must specify the arguments: GetTemperatures( HourlyTemperaturs, NumTemperatures );
I think the problem is that you are confusing multiple variables with the same name as a single variable. For example:
int answer = 42;
void print( int answer )
{
cout << "The answer is " << answer << endl;
}
In this example, there are two variables named 'answer'. The first is a global variable and it has the value 42. The second is a temporary variable local to print(). In other words, it exists inside the function but nowhere else. Since it has the same name as the global variable, the local variable takes precedence (meaning you cannot use the global variable inside the function).
Hope this helps.
PS. You could use the global if you give its full name: cout << [B]::answer[/B] << endl;
Perhaps he would like to use some of the power of STL streams to parse the string.
Use an istringstream.
#include <iostream>
#include <sstream>
#include <string>
int main() {
using namespace std;
string full_name;
string first_name;
cout << "Please enter your full name> ";
getline( cin, full_name );
// Get the first name out of the string
{
istringstream ss( full_name );
ss >> ws;
getline( ss, first_name, ' ' );
}
cout << "Hello " << first_name << endl;
return EXIT_SUCCESS;
}
Hope this helps.
Alas, I'm used to doing this in Delphi. Sorry for the syntax problems in C++.
Ed is close. Jennifer is using C++Builder.
You can set Form2::[B]VertScrollBar[/B]->[B]Position[/B] = 0;
My apologies on ClientOrigin. I just looked it up and it is a read-only property. Alas.
Keep in mind my capitalization might be a little off.
I admire your tenacity and efforts, but either your documentation really stinks or you still need to work on searching it. (I just got BDS 2006 and it's documentation really stinks.)
Hope this helps.
I see no error. What exactly does the error message say?
I think I missing something ?
Yes, you are missing all the words I put in bold in my first response.
Typically all the forms you create in the IDE are automatically created when your application starts. (You can choose which forms are auto-created from the Project->Options menu.) You can see the code that does it by choosing Project->View Source (to see the WinMain() function).
What appears to be happening is that you are Free()ing the form when it is closed, and you can no longer Show() an object that has been destroyed.
From what I understand that you want to do, you should go to the project options and remove the Form2 from the auto-create list. (You can also delete the Form2 variable from the unit source file.)
Next, in your button click handler, (1) create a new instance of the form and (2) show it.
System::Void Form1::button5_Click(System::Object^ sender, System::EventArgs^ e)
{
TForm2 newForm;
Application->CreateForm( TForm2, newForm ); // (1)
newForm.Show(); // (2)
}
Now you can click the button to get as many copies of TForm2 as you want, and closing each one should still delete the individual instance.
Hope this helps.
Yep.
You can set the form's ClientOrigin property (which is a tPoint)
or
You can set the position property of the form's HorzScrollBar and/or VertScrollBar.
Have fun!
A parameter is a temporary variable created by your routine. For example:
void bigger_than_five( int number )
{
result = (number > 5);
}
In this example, number is the parameter (variable).
int main()
{
if (bigger_than_five( 42 )) std::cout << "42 is bigger than 5\n";
else std::cout << "hmm... 42 is not bigger than 5 !\n";
}
In this example, 42 is the argument or value we give to the variable 'number'.
The only place that the variable number exists is inside the function bigger_than_five(). Hence, the following is an error:
int main()
{
number = 42; // error, 'number' doesn't exist!
if (bigger_than_five( number )) std::cout << "blah blah blah\n";
}
I hope this helps.
[edit] Yoinks! I'm slow...
My thoughts exactly. Resource Hacker is a great little utility.
You should be aware, however, that playing around with another program's resources is not always safe. Well-written programs will handle changes gracefully, but those that make assumptions about their resource data may fail.
When you modify the bitmap, try to keep the same bitdepth and compression method (if any).
Good luck!
It comes with time.
Sorry, for the error. I accidentally mixed C and Pascal. The line should read Timer1.Tag := n div 10;
The "extended" is the IEEE 80-bit Extended Precision floating point type. Pascal converts single, double, and real to extended when performing calculations.
Ack! I'm so sorry. I accidentally grabbed the wrong function... It's late and I've got to get some sleep but I'll post it early for you tomorrow.
atish00 The first is an STL header. The second comes with the Windows API.
You need to turn off line buffering using SetConsoleMode. Here is an example function that does that to wait for the user to press a key:
#include <string>
#include <windows.h>
void console::pressanykey( std::string prompt ) {
DWORD mode;
HANDLE hStdIn;
INPUT_RECORD inrec;
DWORD count;
char default_prompt[] = "Press the 'any' key...";
/* Set the console mode to no-echo, raw input, */
/* and no window or mouse events. */
hStdIn = GetStdHandle( STD_INPUT_HANDLE );
if (hStdIn == INVALID_HANDLE_VALUE
or !GetConsoleMode( hStdIn, &mode )
or !SetConsoleMode( hStdIn, 0 ))
return;
if (prompt.empty()) prompt = default_prompt;
/* Instruct the user */
WriteConsole(
GetStdHandle( STD_OUTPUT_HANDLE ),
prompt.c_str(),
prompt.length(),
&count,
NULL
);
FlushConsoleInputBuffer( hStdIn );
/* Wait for and get a single key PRESS */
do ReadConsoleInput( hStdIn, &inrec, 1, &count );
while ((inrec.EventType != KEY_EVENT) || !inrec.Event.KeyEvent.bKeyDown);
/* Restore the original console mode */
SetConsoleMode( hStdIn, mode );
}
Google "msdn SetConsoleMode" for more.
Hope this helps.
What OS are you using?
Miranda has a lot of similarities to Haskell. I can't say for sure that I can help you, but post your question and we'll see.
Even if I can't, there are a lot of knowledgeable Haskell folks here that probably can.
Make sure your form class looks something like this:
type
TForm1 = class(TForm)
...
public:
{ Public declarations }
procedure sendNsecondsWorthOfBtoNotepad( n: integer );
end;
...
implementation
{$R *.RES}
procedure Form1.sendNsecondsWorthOfBtoNotepad( n: integer );
var ...
begin
...
end;
Hope this helps.
"Better" is a subjective word. If you mean in terms of "easier to use complicated code with fewer errors and improved error handling" then OOP is better.
Objects encapsulate information. That is to say, they don't just define related information, but they provide ways to manipulate that information.
One point of note: classes actually make life just a little bit more complicated for the people writing the class. The reward is that classes make life a breeze for people using the class. The tradeoff, however, is slim, since you'd generally have to write all the stuff that gets put in the class anyway, and when in a class it is much more coherent and easy to read.
The Before Way
For example, a non-object oriented thing is an array:
int xs[] = { 2, 3, 5, 7, 11, 13, 17, 19 };
If you want to print this array you have to know something "magical" about it: its length. The magical thing is that, given the array, there is no way to determine its length.
(Now, before those of you in-the-know respond with length = sizeof( xs ) / sizeof( x[0] )
I'll remind you that that only works because the compiler knows how long xs is. That only works in specific cases... when you are executing the program you cannot depend on the compiler's help.)
Suppose, for example, we have a little function to print that array:
void print_ints( int xs[] …
Actually, you've done quite admirably. My score: 1768.
A couple notes though:
int main()
void pause()
{
cout << "Press ENTER to continue..." << flush;
cin.clear(); // (assume the user is playing interactively)
cin.sync(); //
cin.ignore( numeric_limits<streamsize>::max(), '\n' );
}
void clearscreen()
{
for (int i = 0; i < 100; i++) cout << '\n';
cout << flush;
}
You should add a little error checking to validate the user's input, and complain if he enters something wrong. This is a fairly involved subject, so the simplest thing would be simply to wrap everything in a try..catch block and complain if the user enters the wrong thing:
cout<<"Enter the position: ";
try {
if (!(cin>>x_char)) throw 1;
if (!(cin>>y)) throw 1;
x=change(x_char); //change char to int
if (x < 0) throw 1;
skip=check_skip (pos,x,y); //skip step if pos is ' '
}
catch (int) {
cout << "You must type a letter (A..J) followed by a number (0..9) and then press ENTER.\n";
pause();
skip = 1;
}
That timer event will not work like you expect. The Int10 is not guaranteed to have any specific value. While it may appear to work sometimes (just as a fluke of how the stack works), it will suddenly break and work differently.
In either case, you should not enable the timer in a timer event. Only disable.
The way to do it is:
procedure Form1.sendNsecondsWorthOfBtoNotepad( n: integer );
// Add this procedure to the private, protected, or public part of your form class.
begin
timer1.interval := 100; // one keypress every 1/10th second
timer1.tag := n /10; // number of timeout events to process
timer1.enabled := TRUE
end;
procedure Form1.Timer1Timer( sender: tObject );
// This is the timeout event
begin
// Send the keystroke
keybd_event(Ord('B'), 0, 0, 0);
// One tenth second has passed
timer1.tag := timer1.tag -100;
// If time is up, stop sending keystrokes
if timer1.tag = 0 then timer1.enabled := FALSE
end;
procedure Form1.Button1Click( sender: tObject );
// This procedure starts the process
var ms: integer;
begin
// Convert the user's input if possible. (If not, complain.)
try ms := strToInt( edit1.text )
except
showMessage( 'You must specify the number of milliseconds to send keystrokes' );
edit1.setFocus;
exit
end;
sendNsecondsWorthOfBtoNotepad( ms )
end;
Hope this helps.
Hmm, that's right. (Stupid grid controls are poorly designed... they give everyone and everything grief...)
You'll have to help it along. This is what I did. (I used a tStringGrid to test.)
Set DragMode to dmManual. (Sorry about that earlier.)
Set Options.goRangeSelect to FALSE.
procedure Form1.stringGrid1MouseMove(
sender: tObject;
shift: tShiftState;
x, y: integer
);
begin
// If we should be dragging, then start
if ssLeft in shift then stringGrid1.beginDrag( TRUE )
end;
I also used OnStartDrag to create a custom tDragObject (which you'll probably want to do also...). The source argument to OnDragOver and OnDragDrop is the object you create.
My custom object looked like this:
type
TMyDragObject = class( TDragObject )
// Tracks which cell we are dragging, so when we drop
// it we can append its contents to the target cell's text.
public
sCol, sRow: integer; // start col, row
valid: boolean; // convenience
constructor create( aCol, aRow: integer; aValid: boolean );
end;
constructor TMyDragObject.create(
aCol, aRow: integer;
aValid: boolean
);
begin
inherited create;
sCol := aCol;
sRow := aRow;
valid := aValid
end;
And the way I used it:
procedure TForm1.StringGrid1DblClick( Sender: TObject );
begin
// Double-clicks just append an X to the cell's text.
with stringgrid1 do
cells[ col, row ] := cells[ col, row ] +'X';
end;
procedure TForm1.StringGrid1DragDrop(
Sender, Source: TObject;
X, Y: Integer
);
var dCol, dRow: integer;
begin
// Drop the source object onto the cell under the mouse cursor.
// Note that since I used 'OnDragOver' …
Ah, ye olde rodent...
Remember, a (basic) mouse only does two things: move and click (single click, that is).
So, Windows and Delphi and whatever else have to make some basic assumptions about how the user will manipulate the mouse to distinguish things like drag and double-click from normal movement and single clicks.
Unfortunately, you have told Delphi to throw all that out the window and do it your way... (alas!)
To fix it, get rid of all special MouseDown and MouseUp event handler methods.
To handle a double click, provide an event method only for OnDblClick.
To handle dragging, you need to provide for at least the first of the following three:
OnDragDrop
OnStartDrag
OnDragOver
Leave the drag mode as automatic.
In the Object Inspector, switch to the events tab, (single) click on one of those events, and press F1 for more information.
You can also give the control a popup menu, which will be properly (and automatically, so you don't need to worry about it) handled when the user right-clicks with the mouse.
If you want to do anything unusual (like respond to single left-clicks with the Shift key held down, or handle middle-clicks, etc) you can do that too, just don't do anything on a normal left-click.
Hope this helps.
Wow, I learned something.
I've always understood literals in scanf() to be read, matched, and discarded. Apparently that doesn't count for whitespace characters...
Replace every occurrence of %*c
with
\n
[inlinecode]
, and down at lines 39 and 41 change it to
[inlinecode]
scanf( "%lf\n", &cost );
and
scanf( "%lf\n", &price );/inlinecode]
Every time you ask the user for something you can expect him to press ENTER. You need to get rid of that enter key from the input each time you read something. That's what the "\n" does.
Hope this helps.
[EDIT] > Nonstandard!?!?!?
Yoinks! You're right! It is standard.
[EDIT #2] If you know this is the C++ forum, why are you posting C code here?[inlinecode]
scanf( "%lf\n", &price );/inlinecode]
Every time you ask the user for something you can expect him to press ENTER. You need to get rid of that enter key from the input each time you read something. That's what the "\n" does.
Hope this helps.
[EDIT]
> Nonstandard!?!?!?
Yoinks! You're right! It is standard.
[EDIT #2]
If you know this is the C++ forum, why are you posting C code here?
That %*c
is nonstandard. I suspect that you are trying to get rid of the newline.
Instead, get rid of the newline with: scanf( "%d\n", &my_int );
Hope this helps.
BTW, this is the C++ forum.
If you haven't learned to use vectors yet, don't worry about it. (A vector is the STL class that implements a dynamic array.)
What is important is the algorithm suggested to answer your problem. I suggested that you simply read a line at a time. If the line is empty (because the user just pressed ENTER) then you are done getting elements. If the line is not empty, then convert it to an integer (or whatever you asked for) and add it to your array/linked list/whatever.
I said <stringstream> when I should have said <sstream>
. If you had googled "stringstream" like I asked you to you would have found that to use a stringstream you need to include <sstream>.
This is standard C++ code. If your compiler can't handle it you need to upgrade to a better/newer version compiler.
Since this all seems to be going straight over your head, just use the ^Z method. You can check to see if the stream is closed using an if statement.
vector<int> ints;
int i;
while (cin) { // while not at the end of the stream
cin >> i; // get an integer
ints.push_back( i ); // add the integer to the "array" of integers
}
Hope this helps.
It won't be an infinite loop if you break out at some point.
Google the rest of your questions. "string::empty()" and "stringstream" and "vector::push_back".
Sorry I forgot the headers. They are
#include <iostream>
#include <string>
#include <stringstream>
#include <vector>
Enjoy!
Whenever I want the user to enter an array of elements (and this is pretty common too) I always just ask for an extra ENTER at the end (a blank line).
So the program might run something like this:
Please enter the elements of the array.
Press ENTER after each element.
Press ENTER on a blank line to stop.
1
2
3
4
Thank you. The array you entered is: 1 2 3 4.
The way to code this is to use getline() to read each line entered by the user. If it is blank, then stop. If not, use a stringstream to convert the element to whatever you want it to be.
vector<int> ints;
string line;
cout << "Please ...";
while (true)
{
getline( cin, line );
if (line.empty()) break;
stringstream ss( line );
int value;
ss >> value;
ints.push_back( value );
}
cout << "Thank ...";
for (int i = 0; i < ints.size(); i++) cout << ints[ i ];
cout << endl;
Hope this helps.
zhelih
First off, don't just give people code. The whole point of homework is so that the student has to use his brain.
Second off, it doesn't work, because the user can't input the first three numbers properly and it doesn't calculate the average.
sfurlow2
Remember, the average is (sum of numbers entered) / (count of numbers entered).
In C and C++, remember that / is integer division on integers, and floating point division on floats. So int / int is an int. Whereas float / int is a float. You can fix it by casting:
int sum;
int count;
float average;
...
average = float( sum ) / count;
For handling the special cases, consider them separately:
one number entered
the average of one number is itself. (x / 1 = x)
two numbers entered
the average of two numbers is the sum over two. (x + y) / 2
three or more numbers entered
the average is the sum of all the numbers entered over the number of numbers entered:
(x + y + z) / 3
(w + x + y + z) / 4
(v + w + x + y + z) / 4
etc.
Looking at this, you'll recognize that "two numbers entered" is not a special case at all...
In fact, one number entered isn't either.
So you only really need three things:
…You need a loop. Like repeat..until or while..do.
You can also check your answers using a case statement.
You are getting lost on syntactic sugar. ([B]define[/B] (foo x y z) (+ (- x y) z))
is sugar for: ([B]define[/B] foo ([B]lambda[/B] (x y z) (+ (- x y) z)))
Likewise, inside the body of a lambda, using ([B]define[/B] (bar q) (* q (+ q 1))) ...
is sugar for: ([B]letrec[/B] ((bar ([B]lambda[/B] (q) (* q (+ q 1))))) ...)
What I suggest is replacing the lines: ([B]if[/B] ([B]null?[/B] lst) lst
with: ([B]if[/B] ([B]not[/B] ([B]null?[/B] lst))
and see if that works. (I'm not sure if it will or not...)
It is not working because you failed to obey my advice.
Read up on istream::ignore() to find out why it fails.
Between lines 11 and 12 put cin.ignore( numeric_limits<streamsize>::max(), '\n' );
The stream >> operator only reads what you ask it to, and leaves everything else behind in the input buffer. However, whenever dealing with user input you must expect that the user will press the ENTER key after everything you ask him to enter.
getline() reads everything except the ENTER key, stores it in a string, then reads and throws away the ENTER key.
cin >> anything, in contrast, only reads anything, and leaves everything else (including that pesky ENTER key) in the input stream. So the next time you call getline(), it does what it did before, reading '' and sticking it in to a string, then reads the ENTER key and throws it away.
So, after using >> you must explicitly read and throw away that ENTER key so that it isn't still there the next time you try to get input from the user.
Hope this helps.
You might want to remember to load (E)DS at the beginning of your program.
All the functions you are using (with 'call') have a register call type, meaning that arguments are passed in registers. Hence, to settextcolor( attribute: byte ) the attribute must first be placed in AL (as you have done).
Make sure to keep the two parts (loading the registers and calling the function) together for each function. Use commentary to help:
; Set the text attribute to colors[esi]
mov al, [esi]
call settextcolor
; Write a '#' to show the colors
mov al, '#'
call Writechar
etc. The reason I want you to do this is so that you don't make mistakes like you did with gotoxy (which should take two arguments: one in AX and one in BX, if I remember correctly).
Be careful how you use (E)SI. When you change it for the inner loop, you completely loose your place in the outer loop. I would recommend pushing and popping SI and CX at the same places in the code.
; Prepare to enter the inner loop
push si, cx
...
; Prepare to return from the inner loop
pop cx, si
The last thing to think about is how a text color attribute is stored. Remember: four bits for the background and four bits for the foreground. You'll have to use some bit manipulations (shift and add) to combine the current foreground color with the current background color, then settextcolor and …
If you just double click the OnShow property in the Object Inspector (sorry to keep using Borland terminology) the IDE should auto-create an event procedure for you. Borland would name it "FormShow".
OnShow is a property. (Essentially it is a function pointer.) Your function should be named something like void Form1::FormShow( TObject *Sender );
and then you set OnShow = FormShow.
For each form, the OnCreate handler (which it looks like you have named "InitializeComponent"?) should only fire once. Your form is created at the beginning of the program, and no matter how many times you show or hide it, it is only destroyed when the program ends.
It is possible to do things differently, but I wouldn't worry about that for now...
If this doesn't help then please post some complete code that demonstrates your problem...