Разработать графическое приложение windows api с функционалом простого калькулятора

This tutorial will be showed how to create a simple graphical interface using C++ and Visual Studio 2019. This tutorial can be a good kickstart for the future development of Graphical User Interfaces, using C++, Visual Studio 2019, and .Net Framework. Parts Required Microsoft Visual Studio 2019; .NET Framework (automatically installed with Visual Studio). Note:

This tutorial will be showed how to create a simple graphical interface using C++ and Visual Studio 2019.

This tutorial can be a good kickstart for the future development of Graphical User Interfaces, using C++, Visual Studio 2019, and .Net Framework.

Parts Required

  • Microsoft Visual Studio 2019;
  • .NET Framework (automatically installed with Visual Studio).

Note: Below you can check a possible install configuration of Visual Studio. If you want to use the file you change the file (from “vsconfig.txt” to “.vsconfig“) and import when install or modify Microsoft Visual Studio 2019.

Create a new Project

1. Open Visual Studio 2019.

2. Select the type of project.

3. Type the desired name of the project.

Create a design

In order to have a graphical appearance, it is necessary to add Windows Forms to the project.

1. Go to “Project” and click on “Add New Item…“.

2. Select “Windows Form“, change the name of the file if you like, and press “Add“.

Note: If this message appears, restart the Visual Studio should get it away.

Example of a possible error when the project start.
After restart the Visual Studio without errors.

Design Configurations

Now it is necessary to add the necessary visual components in order to get the desired result. You will need 3 labels, 2 textbox, 1 button, 1 flow layout, and 4 checker boxes.

1. In “Toolbox” search for “label“. Then select the “Label” and drag it to “Design” and drop it wherever you want. (In all, 3 labels will be needed.)

Example of label placement.

2. Repeat the process for two “TextBox” and one button.

3. Add a “FlowLayoutPannel“.

4. Search for “CheckBox” and drop it inside of the “FlowLayoutPannel” (you will need 4 in total).

5. Select the “checkBox1” and go to “Properties” and change the “Name“. This name should not have spaces, because is the name used when coding to reference the checkbox.

6. Change “Text” to “+” because is this checkbox that will match the sum operation.

7. Repeat the process to others checkboxes.

8. Change the “Text” of “label1” to “My Calculator”.

9. Change the “Text” of “label2” to “Result:”.

10. Change the “Text” of “label3” to “No Input” and the “Name” to “result_output”.

11. Change the “Name” of “textBox1” to “value1_input” and the “Name” of “textBox2” to “value2_input”.

12. Change the “Text” of “button1” to “Calculate”.

On click event configuration

As the objective is to present the result of a certain operation, it is necessary to create an event that performs the desired operations.

1. Double click on the “Calculate” button, to generate a click event on “MyForm.h“.

2. After double click on the button “MyForm.h” file will open and the event will appear.

3. The button click event must have the following code, as it is in this event that the desired operations will be performed. Since the objective is to change the status of the label “result_output” and display the result of the operation in it.

private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {

		//Assign the value from TextBox to a float variable
		float value1 = (float)System::Convert::ToDouble(value1_input->Text);
		float value2 = (float)System::Convert::ToDouble(value2_input->Text);

		float result;

		//Check the CheckBoxes values and excute the respective operation
		if (bool(check_sum->CheckState)) {
			//Do the sum operation
			result = value1 + value2;
		}
		if (bool(check_sub->CheckState)) {
			//Do the subtraction operation
			result = value1 - value2;
		}
		if (bool(check_mult->CheckState)) {
			//Do the multiplication operation
			result = value1 * value2;
		}
		if (bool(check_div->CheckState)) {
			//Do the division operation
			result = value1 / value2;
		}

		//Update output label
		result_output->Text = System::Convert::ToString(result);

	}

Build configuration

Before building the project, it is necessary to perform some configurations. In the example case, the solution configuration corresponds to Debug mode and an x86 platform. But if you want to develop this project for another configuration (Release Mode, for example), or another platform (x64, for example), just change these fields and carry out the following procedures.

1. Before performing the project settings, there must be the main function so that the windows forms application can be executed. A simple way to do this is to copy and paste the following code into the “MyForm.cpp” file. This indicates how the form should be executed.

#include "MyForm.h"

using namespace System;
using namespace System::Windows::Forms;
[STAThreadAttribute]

void main(array<String^>^ args)
{
	Application::EnableVisualStyles();
	Application::SetCompatibleTextRenderingDefault(false);
	MyCalculator::MyForm form;
	Application::Run(% form);
}

2. On “Solution Explorer“, select your project and right-click on it.

3. In this pop-up, click on “Properties“.

4. Expand “Linker” configurations and click on “Advanced“. On “Entry Point” type “main“, because in this field it is necessary to specify the name of the input function, as an entry point for the file .exe or DLL (it is located in the file “MyForm.cpp”).

5. Select the “System” property on “Linker“. In the option “SubSystem“, select the “Windows” option. After that, click on “OK“.

6. Know it is possible to start without debugging and the GUI should pop up.

Results

Example of successful “Build”.

Enjoy it!!!

Source code  

Download Calculator.zip 

Introduction 

This is the first half of a tutorial on making Windows 8 apps. The goal is to learn how to use Visual Studio 2012, the Windows 8 APIs and the basic tools that they provides. The approach will be to make two simple apps from scratch. In doing so, we will cover some of the basic tools needed to make an interactive user interface. In the first part, we will make a simple calculator and in the second part, we will make a note-taking app. 

I will be using C#/XAML in this tutorial, but note that you can use C++/XAML, C++/DirectX11 or Javascript/HTML to make Windows 8 apps also.

Prerequisites 

The first part of this tutorial is meant to be accessible for people with little to no programming experience. Readers with experience with Windows Form, Windows Phone, Silverlight, WPF development, or similar technologies may prefer to skip to the second part. Knowledge of C# is not required: a good portion of the code I write will be easy to read as English and the reader can simply copy any syntax that is more complex.

Naturally, basic knowledge of C# does help. For this purpose, I recommend following the tutorial on C# Station. Lessons 1-5, 7 and 10 should be sufficient in the scope of this tutorial. This is only one of many options; there are other excellent tutorials out there. 

Having Windows 8 installed is a requirement for making Windows 8 apps. Students can obtain it for free on Dreamspark. The other requirement is to have either the full Visual Studio 2012 or Visual Studio 2012 Express for Windows 8 installed. Both contain the essential features for making apps. The express version can be downloaded for free and students may have access to the full version from their school, via the Dreamspark/MSDN AA. 

Creating a new project 

1) Start by opening Visual Studio. Visual Studio is an integrated development environment (IDE), which will provides a convenient way to compile code and design an interface visually with drag-and-drop, as well as many other features and tools. 

2) Visual Studio comes with a «light» theme and a «dark» theme. In this tutorial, I will be using the «light» theme. You can change it in Menu > Tools > Options > Environment > General > Color Theme, depending on your tastes. 

3) Create a new, blank project in File > New > Project … > Templates > Visual C# > Windows Store > Blank App (XAML). Let’s name it «Calculator». 

Image 1

4) A working template is automatically created. A template is a working application that you can compile and run immediately by pressing F5, though it contains nothing at the moment.

The two files of interest are MainPage.xaml and MainPage.xaml.cs which are located in the Solution Explorer on the right, which is where you find every file contained in the project. The former is the XAML code for your interface. It works like HTML and allows you to specify the location and properties of things such as buttons, menus, etc. The latter is the actual code for your project — code that is used when you interact with the interface. Double-click on MainPage,xaml to open the editor for your interface. 

5) Take a look at the Toolbox on the left of your screen (it might be on auto-collapse by default). It contains useful «controls», interface elements that are premade for you and will make your life much easier. Try dragging a button into your editor. 

Image 2

Note : Click on the image to see the full size. 

6) When the button that you just placed in the interface is selected, you can see a list of its Properties on the right of the screen, under Solution Explorer. You can change color of button, the text inside it, the size of that text, etc. Let’s do the following :  

Change the Width to 200 and the Height to 150.

Change the Fontsize to 50. 

Change the Content to «ADD».  

Drag the button to the center of the screen. 

7) Next we need to add another control that will display the answer of your calculation. TextBLOCK serves this purpose (not to be confused with TextBOX, which we will get to later). Drag a Textblock from the toolbox and place it under your button. You can play with its properties, increase its font size, etc. Name it OutputText.

Image 3

8) Notice that, under the interface editor, you can see that code has automatically been added (it may look slightly different for you, depending on the properties you’ve changed) : 

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    <Button Content="ADD" HorizontalAlignment="Left" Margin="590,302,0,0" VerticalAlignment="Top" Width="200" Height="150" FontSize="50"/>
    <TextBlock x:Name="OutputText" HorizontalAlignment="Left" Margin="590,478,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Height="43" Width="200" FontSize="30"/>
</Grid>   

9) Double-click on the button in the interface editor. When you double-click on a control, it will create in the code editor a function that is called when the button is clicked. The following should have been created in your code (MainPage.xaml.cs) :  

private void Button_Click_1(object sender, RoutedEventArgs e)
{
 
}   

An alternative option is to click on the lightning symbol on the top-right of the properties pane, next to the tool symbol. It will list every possible interaction the control supports, called «events». You can click on the empty space next to an event for Visual Studio to create the function for you.

Note that you should rely on Visual Studio to do it for you. If you simply copy the code in your editor, it may not work, because Visual Studio needs some additional code that I won’t get into in this tutorial. 

10) Before we create a calculator, let’s test our button by making the overused cliche, «Hello World». Don’t copy-paste the code below : type it yourself. Notice that as you are typing, Visual Studio suggests possible auto-completions. This feature is called Intellisense, which, in this case, brings up all the properties of a given object — OutputText.

private void Button_Click_1(object sender, RoutedEventArgs e)
{
    OutputText.Text = "Hello World!";
}   

 Image 4

11) You can now test your app. To do so, either press F5 or click on the green arrow button in the menu, which should say «Local Machine» (choosing simulator will open an emulator for a tablet that supports rotation changes, but we don’t need that here). To exit your app, return to the desktop via Windows-D and terminate your app by pressing on the red square. If you don’t, the app is still running and you cannot make code changes. 

12) Now let’s make a calculator. The user will need to enter two numbers. Drag two TextBOX from the toolbox to the editor, on top of your button. Name them Input1 and Input2.  Change their properties, such as font size, if desired. 

Image 5

13) Finally, we will change the code for Button_Click_1. The user enters text in the two textboxes. We want to add numbers. So we will convert the input to numbers, add them, and convert it back to text again, using the build in «Convert» functions. 

private void Button_Click_1(object sender, RoutedEventArgs e)
{
    OutputText.Text = Convert.ToString(Convert.ToInt32(Input1.Text) +
                Convert.ToInt32(Input2.Text));
}   

14) Run your app and watch the magic happen.  

Going further… 

We would expect additional features in a calculator. Subtraction, multiplication and division follow the same concepts as addition. It would be redundant in this tutorial to repeat the same steps — however, as an exercise, I would suggest trying to implement those. 

We have only using some of the properties of controls, mainly location, size and fontsize. Can you play with the controls in the editor, change their properties and try to make the calculator look better? 

Source code  

Download Calculator.zip 

Introduction 

This is the first half of a tutorial on making Windows 8 apps. The goal is to learn how to use Visual Studio 2012, the Windows 8 APIs and the basic tools that they provides. The approach will be to make two simple apps from scratch. In doing so, we will cover some of the basic tools needed to make an interactive user interface. In the first part, we will make a simple calculator and in the second part, we will make a note-taking app. 

I will be using C#/XAML in this tutorial, but note that you can use C++/XAML, C++/DirectX11 or Javascript/HTML to make Windows 8 apps also.

Prerequisites 

The first part of this tutorial is meant to be accessible for people with little to no programming experience. Readers with experience with Windows Form, Windows Phone, Silverlight, WPF development, or similar technologies may prefer to skip to the second part. Knowledge of C# is not required: a good portion of the code I write will be easy to read as English and the reader can simply copy any syntax that is more complex.

Naturally, basic knowledge of C# does help. For this purpose, I recommend following the tutorial on C# Station. Lessons 1-5, 7 and 10 should be sufficient in the scope of this tutorial. This is only one of many options; there are other excellent tutorials out there. 

Having Windows 8 installed is a requirement for making Windows 8 apps. Students can obtain it for free on Dreamspark. The other requirement is to have either the full Visual Studio 2012 or Visual Studio 2012 Express for Windows 8 installed. Both contain the essential features for making apps. The express version can be downloaded for free and students may have access to the full version from their school, via the Dreamspark/MSDN AA. 

Creating a new project 

1) Start by opening Visual Studio. Visual Studio is an integrated development environment (IDE), which will provides a convenient way to compile code and design an interface visually with drag-and-drop, as well as many other features and tools. 

2) Visual Studio comes with a «light» theme and a «dark» theme. In this tutorial, I will be using the «light» theme. You can change it in Menu > Tools > Options > Environment > General > Color Theme, depending on your tastes. 

3) Create a new, blank project in File > New > Project … > Templates > Visual C# > Windows Store > Blank App (XAML). Let’s name it «Calculator». 

Image 1

4) A working template is automatically created. A template is a working application that you can compile and run immediately by pressing F5, though it contains nothing at the moment.

The two files of interest are MainPage.xaml and MainPage.xaml.cs which are located in the Solution Explorer on the right, which is where you find every file contained in the project. The former is the XAML code for your interface. It works like HTML and allows you to specify the location and properties of things such as buttons, menus, etc. The latter is the actual code for your project — code that is used when you interact with the interface. Double-click on MainPage,xaml to open the editor for your interface. 

5) Take a look at the Toolbox on the left of your screen (it might be on auto-collapse by default). It contains useful «controls», interface elements that are premade for you and will make your life much easier. Try dragging a button into your editor. 

Image 2

Note : Click on the image to see the full size. 

6) When the button that you just placed in the interface is selected, you can see a list of its Properties on the right of the screen, under Solution Explorer. You can change color of button, the text inside it, the size of that text, etc. Let’s do the following :  

Change the Width to 200 and the Height to 150.

Change the Fontsize to 50. 

Change the Content to «ADD».  

Drag the button to the center of the screen. 

7) Next we need to add another control that will display the answer of your calculation. TextBLOCK serves this purpose (not to be confused with TextBOX, which we will get to later). Drag a Textblock from the toolbox and place it under your button. You can play with its properties, increase its font size, etc. Name it OutputText.

Image 3

8) Notice that, under the interface editor, you can see that code has automatically been added (it may look slightly different for you, depending on the properties you’ve changed) : 

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    <Button Content="ADD" HorizontalAlignment="Left" Margin="590,302,0,0" VerticalAlignment="Top" Width="200" Height="150" FontSize="50"/>
    <TextBlock x:Name="OutputText" HorizontalAlignment="Left" Margin="590,478,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Height="43" Width="200" FontSize="30"/>
</Grid>   

9) Double-click on the button in the interface editor. When you double-click on a control, it will create in the code editor a function that is called when the button is clicked. The following should have been created in your code (MainPage.xaml.cs) :  

private void Button_Click_1(object sender, RoutedEventArgs e)
{
 
}   

An alternative option is to click on the lightning symbol on the top-right of the properties pane, next to the tool symbol. It will list every possible interaction the control supports, called «events». You can click on the empty space next to an event for Visual Studio to create the function for you.

Note that you should rely on Visual Studio to do it for you. If you simply copy the code in your editor, it may not work, because Visual Studio needs some additional code that I won’t get into in this tutorial. 

10) Before we create a calculator, let’s test our button by making the overused cliche, «Hello World». Don’t copy-paste the code below : type it yourself. Notice that as you are typing, Visual Studio suggests possible auto-completions. This feature is called Intellisense, which, in this case, brings up all the properties of a given object — OutputText.

private void Button_Click_1(object sender, RoutedEventArgs e)
{
    OutputText.Text = "Hello World!";
}   

 Image 4

11) You can now test your app. To do so, either press F5 or click on the green arrow button in the menu, which should say «Local Machine» (choosing simulator will open an emulator for a tablet that supports rotation changes, but we don’t need that here). To exit your app, return to the desktop via Windows-D and terminate your app by pressing on the red square. If you don’t, the app is still running and you cannot make code changes. 

12) Now let’s make a calculator. The user will need to enter two numbers. Drag two TextBOX from the toolbox to the editor, on top of your button. Name them Input1 and Input2.  Change their properties, such as font size, if desired. 

Image 5

13) Finally, we will change the code for Button_Click_1. The user enters text in the two textboxes. We want to add numbers. So we will convert the input to numbers, add them, and convert it back to text again, using the build in «Convert» functions. 

private void Button_Click_1(object sender, RoutedEventArgs e)
{
    OutputText.Text = Convert.ToString(Convert.ToInt32(Input1.Text) +
                Convert.ToInt32(Input2.Text));
}   

14) Run your app and watch the magic happen.  

Going further… 

We would expect additional features in a calculator. Subtraction, multiplication and division follow the same concepts as addition. It would be redundant in this tutorial to repeat the same steps — however, as an exercise, I would suggest trying to implement those. 

We have only using some of the properties of controls, mainly location, size and fontsize. Can you play with the controls in the editor, change their properties and try to make the calculator look better? 

Back to Software

8 May 2017
Progress: Complete

Why? Why would we want to go and do something like recreate windows calculator? I must admit that having bedded myself quite comfortably in the world of Javascript, where every user interface is instantly, universally cross-platform, diving into the Windows API does seem like a step backwards. But it’s educational. It’s one of those rights-of-passage things.

The Windows API lets you build graphical applications in C. In the past I’ve always used huge libraries for GUIs, but there’s a certain shame associated with it – even the simplest application usually ends up a good chunk of a megabyte. Doing the same with just the Windows API should produce an .exe file of only a couple kilobytes.

Like many things, once you get started you realize it’s actually quite easy. The first step is setting up the build environment. There are many C compilers out there, but the one I chose here was lcc-win32. This is an old, proprietary C compiler for windows, with an utterly abysmal IDE, but it’s extremely lightweight, the whole install was something like 20MB.

Windows API

All we need to do to start using windows API calls is include windows.h :

#include <windows.h>

int main(void) {
  MessageBox(NULL, "Hello World", "Hello", MB_OK);
  return 0;
}

Hello world in an alert box

Woohoo. The first parameter is the «parent window» which the message box belongs to. We haven’t made one yet so we leave it null (normally, if you click on the parent window while a message box is open, it flashes the title bar of the message again). The last parameter is a bitwise flag which can be used to change the styling.

Lcc-win32 is supposed to come with an offline reference for the Windows API, but I couln’t use it for some reason. So the only reference we have is MSDN, which is pretty bloated and slow. Generally just Googling «winapi messagebox» or whatever finds plenty of information on it. It may be an old technology, but that’s a good thing: every problem you encounter has probably been solved a dozen times already.

There’s a certain amount of terminology that we need to be aware of. Everything is a «window», even buttons or text edit boxes. What we’d call a «text input» or «textarea» in HTML are called an «EDIT» window, which needs the ES_MULTILINE flag set to be a textarea. ES stands for Edit Style.

Note that for all but the most trivial programs, we don’t use main() as our entry point function, rather WinMain(). No doubt some stuff goes on in the background. It also hands us some useful parameters.

Windows programming is generally event-based. Windows uses a message queue, messages come in, get looked at, then get dispatched again. These messages range from «this button was clicked» to «the screen is about to be redrawn». Unlike Javascript, the program’s message loop is part of our code, so we can change it or put code outside of it if needed.

  MSG Msg;

  while(GetMessage(&Msg, NULL, 0, 0) > 0) 
  {
    TranslateMessage(&Msg);
    DispatchMessage(&Msg);
  }

GetMessage() blocks execution until the next message comes in; another function, PeekMessage() returns immediately if the queue is empty. TranslateMessage() specifically looks at keyboard events and generates new messages based on vitual key codes (i.e. independent of keyboard layout, which is usually more useful). DispatchMessage() sends the message to the window procedure – this is a function we need to provide when we create our window class.

If we want to create a button, we call CreateWindow() with the «BUTTON» class. If we want to make our own type of window, such as the main window of our application, we register our own window class. There are a bunch of trivial parameters to the window class, but the important one is the window procedure. This gets called whenever that window receives a message. Inside it, there is nearly always a big switch statement which splits the messages by ID, then possibly further by their parameters.

When we call CreateWindow with our window class, we can then give it lots of window style flags, such as if it’s resizeable, has min/maximize buttons in the top corner, etc. CreateWindow seems to have been superseded with a similar function, CreateWindowEx, which has an extra parameter, to accept even more style flags. There are extensive lists of possible styles on MSDN, but I’m not sure if it’s worth linking to since the URLs appear to keep changing.

There are many tutorials on the Windows API out there, this summary is mostly just to remind myself. So, let’s get started on our calculator.

The buttons and the display

There are two ways to fill our main window with child windows (the buttons). They can either be created manually, or loaded from a resource file. The resource file is a list of things that would be boring to type out, and most IDEs have resource editors so you can visually lay out your dialog boxes and such. But, I like to keep things simple, so, to hell with resource files.

In the main window procedure we process a message called WM_CREATE. At this point we can have a bunch more CreateWindow() calls to make our buttons. Since they’re all nearly identical I defined a macro for it.

#define makeButton(name,id,x,y,w,h) CreateWindow("BUTTON",name,WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, x,y,w,h, hwnd,(HMENU)(id),GetModuleHandle(NULL),NULL)

Notice that the ID parameter goes into the hMenu (handle to menu) argument, even needs to be cast to type HMENU. Don’t ask me why, but that’s where the ID goes. When the main window procedure receives the WM_COMMAND message, the wParam parameter will contain the ID of the button clicked.

It would be tedious to #define an ID for every button, so I just numbered them 100 to 109 for buttons 0 to 9.

We also need to create an EDIT control as the display. This will be disabled ( ES_READONLY ) but being a text box means the user can select and copy the text easily.

Some logic

A number button gets pressed, we need to push its value onto the display. We use GetWindowTextLength(), then GetDlgItemText() to load this into a char array. It’s a null terminated string, so to append all we need to do is set the last element (null) to the new number, and set the following element to null. Then SetDlgItemText() writes it back to the display.

To get the number from the ID, by the way I defined it (possibly lacking foresight) we need to subtract 100, then add the ascii value of the character zero.

When we start calculating, we need that number as a float. Or actually a long double float, since we want our calculator to be nice and precise. We can use the standard function strtold(), which is like strtof() but longer and doublier. To write values back to the display I used sprintf().

And with that a basic calculator appears to be functioning! There are some subtleties to the behaviour, for instance, pressing buttons in a nonsensical order has a defined behaviour in the real windows calculator. And pressing equals again repeats the last operation. I’ve been doing so much embedded programming lately that I always worry about efficiency, but here I have to remind myself that there is completely negligible cost in adding a few extra variables to keep track of these things.

Screenshot of the Amazing calculator

Keyboard

The real windows calculator can be operated by keyboard events. In fact it’s pretty useless without it. We can listen to the WM_KEYDOWN messages to implement this. We could send the appropriate button-click message back into the queue in response, but instead I just put the case statement for the keydown events directly above the button click events, and let it fall through.

To find the keycodes I got it to open a message box with the parameter value on each keydown event. I may be doing this the hard way, but for the number 8, it could also be the asterisk which would correspond to multiply. This means we have to track shift as well, but that’s easy enough to do. A single line for the WM_KEYUP event zeros our shift variable.

With the keycode known, we then write new values into the wParam corresponding to the button ID, and let it fall into the WM_COMMAND case statement.

This works great until we start mixing mouse clicks with keyboard presses. The keydown message is sent to the window that has focus. At the beginning the main window has focus, but after a button is clicked, it’s the button that captures all the key events, and our keyboard code stops working. Trying to SetFocus() back to the main window doesn’t really work, since by the time the keyboard events come in, it’s too late, and doing it on button clicks causes them to not visually depress properly. Instead, I decided to modify the message loop:

  while(GetMessage(&Msg, NULL, 0, 0) > 0) {
    if (Msg.message == WM_KEYDOWN || Msg.message == WM_KEYUP) Msg.hwnd = hwnd;
    TranslateMessage(&Msg);
    DispatchMessage(&Msg);
  }

Doing this, all keyup and keydown events are now redirected to the main window (hwnd, declared earlier). In a remarkably satisfying way, this method works perfectly.

Conclusion

That about sums up my windows calculator experience. The windows API. Not so scary really. The full source code is below, just a single .c file, no resources or headers. Also, on the odd chance you want it and if you dare download it, the compiled .exe file.

#include <windows.h>
#include <stdio.h>

#define windowClassName "myWindowClass"
#define IDC_EDIT 500

int typing = 0;
BOOL final=0;
long double num1=0.0;
long double num2=0.0;
int op=0;
BOOL shift=0;

long double getScreen(HWND hwnd){
  int len = GetWindowTextLength(GetDlgItem(hwnd, IDC_EDIT));
  char buf[32];
  if (len>0) {
    GetDlgItemText(hwnd, IDC_EDIT, buf, len+1);
    return strtold(buf,NULL);
  }
  return 0.0;
};

void equate(HWND hwnd){
  switch (op) {
    case 110: num1 += num2; break;
    case 111: num1 -= num2; break;
    case 112: num1 *= num2; break;
    case 113: num1 /= num2; break;
  }
  char buf[32];
  sprintf(buf,"%.16Lg",num1);
  SetDlgItemText(hwnd, IDC_EDIT, buf);
}

//the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {

  switch(msg) {
    case WM_CREATE:
    {

      #define errorIfNull(x) if (NULL==x) MessageBox(hwnd, "Error: WM_CREATE", "Error", MB_OK | MB_ICONERROR);

      #define makeButton(name,id,x,y,w,h) errorIfNull(CreateWindow("BUTTON",name,WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, x,y,w,h, hwnd,(HMENU)(id),GetModuleHandle(NULL),NULL))

      errorIfNull(CreateWindowEx(
        WS_EX_CLIENTEDGE,
        "EDIT",
        "0",        // default text
        WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | ES_RIGHT | ES_READONLY, // Disabled, right align
        10,         // x position
        10,         // y position
        206,        // width
        25,         // height
        hwnd,       // Parent window
        (HMENU)IDC_EDIT,  // menu handle = ID
        GetModuleHandle(NULL), NULL));

      makeButton(".",99, 94,178,36,36);
      makeButton("0",100,10,178,78,36);
      makeButton("1",101,10,136,36,36);
      makeButton("2",102,52,136,36,36);
      makeButton("3",103,94,136,36,36);
      makeButton("4",104,10,94,36,36);
      makeButton("5",105,52,94,36,36);
      makeButton("6",106,94,94,36,36);
      makeButton("7",107,10,52,36,36);
      makeButton("8",108,52,52,36,36);
      makeButton("9",109,94,52,36,36);

      makeButton("+",110,136,178,36,36);
      makeButton("-",111,136,136,36,36);
      makeButton("*",112,136,94,36,36);
      makeButton("/",113,136,52,36,36);

      makeButton("=",114,178,136,36,78);
      makeButton("C",115,178,94,36,36);

    }
    break;
    case WM_KEYUP:
      if (wParam==VK_SHIFT) shift=0;
    break;

    case  WM_KEYDOWN :
      if (shift) {
        if (wParam==0x38) wParam=112; // shift 8 = multiply
        else if (wParam==0xbb) wParam=110;
        else break;
      } else {
        if (wParam>=0x30 && wParam <=0x39) {
          wParam+= 100-0x30;
        } else if (wParam>=0x60 && wParam <=0x69) { //numpad
          wParam+= 100-0x60;
        } else switch (wParam){
          case VK_SHIFT: shift=1; return 0;
          case VK_MULTIPLY: wParam =112; break;
          case VK_SUBTRACT: case 0xbd: wParam =111; break;
          case VK_ADD: wParam =110; break;
          case VK_DIVIDE: case 0xbf: wParam =113; break;
          case VK_DECIMAL: case 0xbe: wParam =99; break;
          case VK_RETURN: case 0xbb: wParam = 114; break;
          case 0x2e: wParam = 115; break;

          default:
            return 0;
        }
      }

    // break; Fall through
    case WM_COMMAND:
    {
      switch (wParam) {
        case 99:
          if (typing==2) break;

        case 109:case 108:case 107:case 106:case 105:case 104:case 103:case 102:case 101:case 100:
        {
          char out[32];
          int len = GetWindowTextLength(GetDlgItem(hwnd, IDC_EDIT));

          if (typing) {
            GetDlgItemText(hwnd, IDC_EDIT, out, len+1);
          } else {
            typing=1;
            len=0;
          }
          if (len<=16) {
            if (wParam==99) {
              if (len==0) out[len++]='0';
              out[len]='.';
              typing=2;
            } else out[len] = '0'+(wParam-100);
            out[len+1] =0;
            SetDlgItemText(hwnd, IDC_EDIT, out);
          }

          if (final) op=0;
          final=0;

        }
        break;
        case 111:
        case 110:
        case 112:
        case 113:
          if (typing && op) {
            num2 = getScreen(hwnd);
            equate(hwnd);
          } else num1 = getScreen(hwnd);
          typing=0;
          op=wParam;
          final=0;

        break;
        case 114: // =
          if (!op) break;
          if (typing)
            num2 = getScreen(hwnd);
          typing=0;

          equate(hwnd);
          final=1;

        break;
        case 115: // Clear
          num1=0.0;
          num2=0.0;
          op=0;
          final=0;
          typing=0;
          SetDlgItemText(hwnd, IDC_EDIT, "0");
        break;
      }
    }
    break;
    case WM_CLOSE:
      DestroyWindow(hwnd);
    break;
    case WM_DESTROY:
      PostQuitMessage(0);
    break;
    default:
      return DefWindowProc(hwnd, msg, wParam, lParam);
  }
  return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
  WNDCLASSEX wc;
  HWND hwnd;
  MSG Msg;

  wc.cbSize    = sizeof(WNDCLASSEX);
  wc.style     = 0;
  wc.lpfnWndProc   = WndProc;
  wc.cbClsExtra  = 0;
  wc.cbWndExtra  = 0;
  wc.hInstance   = hInstance;
  wc.hIcon     = LoadIcon(NULL, IDI_APPLICATION);
  wc.hCursor     = LoadCursor(NULL, IDC_ARROW);
  wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  wc.lpszMenuName  = NULL;
  wc.lpszClassName = windowClassName;
  wc.hIconSm     = LoadIcon(NULL, IDI_APPLICATION);

  if(!RegisterClassEx(&wc)) {
    MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
    return 0;
  }

  hwnd = CreateWindowEx(
    0,
    windowClassName,
    "Amazing calculator",
    WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
    CW_USEDEFAULT, CW_USEDEFAULT, 231, 250,
    NULL, NULL, hInstance, NULL);

  if(hwnd == NULL) {
    MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
    return 0;
  }

  ShowWindow(hwnd, nCmdShow);
  UpdateWindow(hwnd);

  while(GetMessage(&Msg, NULL, 0, 0) > 0) {
    if (Msg.message == WM_KEYDOWN || Msg.message == WM_KEYUP) Msg.hwnd = hwnd;
    TranslateMessage(&Msg);
    DispatchMessage(&Msg);
  }
  return Msg.wParam;
}

В статье «Делаем консольный калькулятор.» мы создавали небольшой калькулятор, который работает в консоли. В этой статье пришло время научиться создавать графический калькулятор на языке C# с помощью Windows Forms.

Сам по себе калькулятор довольно прост, но если вы совсем новичок в создании подобных приложений, тогда будет посложнее. Разработку калькулятора начнем с разработки формы (Windows Forms) приложения. Запускаем Visual Studio и создаем проект:

Создание графического калькулятора

Интерфейс созданного проекта должен выглядеть так:

Создание графического калькулятора

На интерфейсе мы видим: слева панель элементов для нашей формы, справа обозреватель решений и свойства выбранной формы/элемента и по середине виден сам конструктор с формой (по умолчанию он имеет имя «Form1»).

На форму нужно поместить кнопки, текстовое поле, а также надпись. Надпись нужна, чтобы пользователь видел первый операнд. Когда введет нужную цифру, нажмет кнопку, например «+», надпись будет содержать введенное значение.

Все нужные элементы можно найти слева в панели элементов. Чтобы найти текстовое поле просто введите в поиске «textBox» и с помощью мышки перенесите его на свою форму. Для добавления кнопок просто введите в поиске «Button» и перенесите нужное количество кнопок на свою форму. Также добавьте на «ListBox» один пустой «Label»:

Создание графического калькулятора

Изменять свойства формы можно с помощью окна «Свойства» справа внизу. Для этого нажмите на нужную форму, например «Button1» и поменяйте ему свойство «text» на «С»:

Создание графического калькулятора

Добавьте все нужные кнопки. Измените свойство «Font» для элементов TextBox и Label. Цвет кнопок и имя программы меняйте на свое усмотрение.

Создание графического калькулятора

С помощью «MultiLine» измените ширину элемента TextBox:

Создание графического калькулятора

В итоге у нас получилось 19 кнопок Button, 1 TextBox и ещё 1 пустой Label:

Создание графического калькулятора

Теперь посмотрим, как работает калькулятор. Мы используем четыре члена класса. Напишем их в самое начало программы:

    float a, b;
    int oper;
    bool znak = true;

Первые два — это наши операнды, a и b. Третий — это выбранный пользователем оператор. Четвертый — признак знака. Запрограммируем обработчик кнопки «+/-«, изменяющий знак числа. Для этого в форме нажмите на нужную кнопку два раза. Visual Studio переведет вас в нужную секцию кода:

        private void button3_Click(object sender, EventArgs e)
        {

        }

В фигурных скобках пишем код:

            if (znak == true)
            {
                textBox1.Text = "-" + textBox1.Text;
                znak = false;
            }
            else if (znak==false)
            {
                textBox1.Text = textBox1.Text.Replace("-", "");
                znak = true;
            }

Если znak=true, мы меняем знак операнда в textBox1, а если false, то знак числа удаляется из текстового поля.

Для каждой цифровой кнопки обработчик будет следующий:

// Обработчик цифровой кнопки "0"

textBox1.Text = textBox1.Text + 0;

На основе этого кода повесьте на цифровые кнопки от 0 до 9 обработчик событий. Нажмите на нужную цифровую кнопку и впишите код.

Обработчик кнопки операторов «+, -, *, /». Нажмите на нужную кнопку с оператором и впишите код.

            // Обработчик оператора "+"

            a = float.Parse(textBox1.Text);
            textBox1.Clear();
            oper = 1;
            label1.Text = a.ToString() + "+";
            znak = true;

В данном коде мы в переменную «a» записываем значение из текстового поля, попутно преобразовав его в float посредством вызова метода float.Parse(). Далее мы очищаем текстовое поле, чтобы можно было вводить второй операнд. oper = 1 означает присвоение номера оператора (для + — это 1 и так далее по увеличению). Далее заносим в надпись информацию об операнде и операторе.

Обработчик кнопки «,» добавляет запятую в текстовое поле:

textBox1.Text = textBox1.Text + ",";

Далее нам понадобится создать функцию, которая будет применять нужные нам математические операции к числам. Назовём её calculate. Но перед этим мы кликнем дважды на кнопку «=» на форме и в коде к ней мы запишем:

// вызов функции
calculate();
label1.Text = "";

При нажатии пользователем на кнопку «=» выполнится функция подсчёта calculate, и, заодно, очистится Label, так как результат мы в будущем коде выведем в TextBox.

Функция calculate:

        private void calculate()
        {
            switch (oper)
            {
                case 1:
                    b = a + float.Parse(textBox1.Text);
                    textBox1.Text = b.ToString();
                    break;
                case 2:
                    b = a - float.Parse(textBox1.Text);
                    textBox1.Text = b.ToString();
                    break;
                case 3:
                    b = a * float.Parse(textBox1.Text);
                    textBox1.Text = b.ToString();
                    break;
                case 4:

                    if (float.Parse(textBox1.Text) == 0)
                    { textBox1.Text = "Делить на 0 нельзя!"; }
                    else
                    {
                        b = a / float.Parse(textBox1.Text);
                        textBox1.Text = b.ToString();
                    }
                    break;
                default:
                    break;
            }

        }

Здесь мы используем конструкцию switch-case. Нам осталось обработать две кнопки:

Обработчик кнопки «С». Данная кнопка будет очищать все записи из TextBox’a и Label’a. Код кнопки:

textBox1.Text = "";
label1.Text = "";

Кнопка «<–» будет удалять последнюю цифру записанного в TextBox’e числа. Код кнопки:

            int lenght = textBox1.Text.Length - 1;
            string text = textBox1.Text;
            textBox1.Clear();
            for (int i = 0; i < lenght; i++)
            {
                textBox1.Text = textBox1.Text + text[i];
            }

Мы вводим новую переменную lenght целочисленного типа и записываем в неё количество символов в TextBox’e минус один символ.

Также мы вводим новую переменную text, в которую полностью заносим текст из TextBox’а. Затем мы очищаем TextBox и вводим цикл for, через который записываем в TextBox строку text, но уже на символ короче.

Теперь наш графический калькулятор готов к работе. Скомпилируйте программу, нажав на «Пуск». Если все заработало и калькулятор делает вычисления, тогда вы все правильно сделали и теперь можете пользоваться свомим личным графическим калькулятором.

Создание графического калькулятора

Методическая разработка по теме

«Создание простого калькулятора на языке С#

с использованием технологии Windows Forms».

Дисциплина:
Информационные технологии и платформы разработки информационных систем

Специальности
технического профиля

Курс: 4

Тип урока: практическая
работа

Ход практической работы

Для создания графического
проекта нам потребуется среда разработки Visual Studio. На компьютерах
установлена  версия Visual Studio 2013.

Логотипом и иконкой Visual Studio 2013
является символ, похожий на математический символ «бесконечность», но
с неодинаковыми левой и правой частями, фиолетового цвета.

1.     
Щелкнув по этой иконке на
панели инструментов, выполняем вход в Visual
Studio
 2013.

В результате сначала
появляется вертикально расположенный баннер Visual Studio 2013 (черного цвета), а затем — стартовая
страница

2.     
Создадим проект графического
приложения.

Для этого  выберете пункт
Создать проект. После этого откроется диалоговое окно создания нового
проекта:

3.     
В поле внизу задайте имя
данному проекту –
ProstoCalculator. Нажмите ОК.

После этого Visual Studio
откроет наш проект с созданными по умолчанию файлами:

 

Большую часть пространства Visual Studio занимает графический
дизайнер, который содержит форму будущего приложения. Пока она пуста и имеет
только заголовок Form1. Справа находится окно файлов решения/проекта — Solution
Explorer (Обозреватель решений). Там и находятся все связанные с нашим приложением
файлы, в том числе файлы формы Form1.cs.

Внизу справа находится окно свойств — Properties. Так как в данный
момент выбрана форма как элемент управления, то в этом поле отображаются
свойства, связанные с формой.

4.     
Теперь найдем в этом окне
свойство формы Text и изменим его значение на «Калькулятор»:

5.     
Далее расположите все нужные
элементы на форме. Нам понадобятся три элемента TextBox и 4 кнопки – Button.

Для этого нажимаем Вид →
Панель элементов:

Появляется Панель
элементов
, из которой будем брать необходимые элементы TextBox и Button
простым перетаскиванием.

Устанавливаем их так, как
показано на рисунке ниже и переименовываем кнопки в свойствах. Сделать это
можно, выделив элемент:

 

6.     
Наш калькулятор основан на взаимодействии
двух чисел, поэтому математические операции будут следующие:

·        
Сложение

·        
Вычитание

·        
Умножение

·        
Деление

7.     
Итак, после того, как с
графическим оформлением закончено, приступаем к самому коду.

Для всех вышеописанных
операций (Сложение, Вычитание, Умножение, Деление) мы должны создать отдельные
функции. Функции – это подпрограммы в самой программе, выполняющие отдельные
задачи. Они помогают сократить и облегчить код.

Вот так  будут выглядеть
функции сложения, вычитания, умножения и деления:

1.      public
static double sum(double a, double b)

2.      {

3.      return
a + b;

4.      }

5.      public static double razn(double a, double b)

6.      {

7.      return a — b;

8.      }

9.      public static double umnog(double a, double b)

10.  {

11.  return a * b;

12.  }

13.  public static double del(double a, double b)

14.  {

15.  return a / b;

16.  }

Данный фрагмент кода помещаем на форму. Для
этого выполним следующие действия:

Кликните в любое пустое место формы
дважды, у вас появится окно с кодом, уже сформированным программой.

Мы дополним код, разместив наш фрагмент 
перед строчкой

private void button1_Click(object
sender,
EventArgs e)

У вас должно получиться:

8.     
Затем данные функции
привязываем к кнопкам в форме.

Дважды щёлкаем мышью в
форме на первую кнопку (Сложение).

Открывается та часть
кода, которая отвечает за событие, которое произойдет, когда пользователь
кликнет на данную кнопку. В теле этого события мы пишем:

·        
private void button1_Click(object sender, EventArgs e)

·        
{

·        
textBox3.Text = Convert.ToString(sum(Convert.ToDouble(textBox1.Text), Convert.ToDouble(textBox2.Text)));

·        
}

        Нажимаем на кнопку 2 (Вычитание):

·        
private void button2_Click(object sender, EventArgs e)

·        
{

·        
textBox3.Text = Convert.ToString(razn(Convert.ToDouble(textBox1.Text), Convert.ToDouble(textBox2.Text)));

·        
}

        Нажимаем на кнопку 3 (Умножение): 

·        
private void button3_Click(object
sender, EventArgs e)

·        
{

·        
textBox3.Text =
Convert.ToString(umnog(Convert.ToDouble(textBox1.Text),
Convert.ToDouble(textBox2.Text)));

·        
}

Нажимаем на кнопку 4 (Деление):

·        
private void button4_Click(object
sender, EventArgs e)

·        
{

·        
textBox3.Text =
Convert.ToString(del(Convert.ToDouble(textBox1.Text),
Convert.ToDouble(textBox2.Text)));

·        
}

У вас должно
получиться:

Вот и всё. Наш калькулятор готов!

 

Дальнейших успехов Вам!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
// MFCCalcDlg.cpp : implementation file
//
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1995 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.
 
#include "stdafx.h"
#include "MFCCalc.h"
#include "MFCCalcDlg.h"
 
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
 
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
 
class CAboutDlg : public CDialog
{
public:
    CAboutDlg();
 
// Dialog Data
    //{{AFX_DATA(CAboutDlg)
    enum { IDD = IDD_ABOUTBOX };
    //}}AFX_DATA
 
// Implementation
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    //{{AFX_MSG(CAboutDlg)
    virtual BOOL OnInitDialog();
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};
 
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
    //{{AFX_DATA_INIT(CAboutDlg)
    //}}AFX_DATA_INIT
}
 
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CAboutDlg)
    //}}AFX_DATA_MAP
}
 
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
    //{{AFX_MSG_MAP(CAboutDlg)
        // No message handlers
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()
 
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg message handlers
 
BOOL CAboutDlg::OnInitDialog()
{
    CDialog::OnInitDialog();
 
    // TODO: Add extra initialization here
    
    return TRUE;
}
 
/////////////////////////////////////////////////////////////////////////////
// CCalcDlg dialog
 
IMPLEMENT_DYNCREATE(CCalcDlg, CDialog)
 
BEGIN_DISPATCH_MAP(CCalcDlg, CDialog)
    //{{AFX_DISPATCH_MAP(CCalcDlg)
    DISP_PROPERTY_EX(CCalcDlg, "Accum", GetAccum, SetAccum, VT_I4)
    DISP_PROPERTY_EX(CCalcDlg, "Operand", GetOperand, SetOperand, VT_I4)
    DISP_PROPERTY_EX(CCalcDlg, "Operation", GetOperation, SetOperation, VT_I2)
    DISP_PROPERTY_EX(CCalcDlg, "Visible", GetVisible, SetVisible, VT_BOOL)
    DISP_FUNCTION(CCalcDlg, "Evaluate", Evaluate, VT_BOOL, VTS_NONE)
    DISP_FUNCTION(CCalcDlg, "Clear", Clear, VT_EMPTY, VTS_NONE)
    DISP_FUNCTION(CCalcDlg, "Display", Display, VT_EMPTY, VTS_NONE)
    DISP_FUNCTION(CCalcDlg, "Close", Close, VT_EMPTY, VTS_NONE)
    DISP_FUNCTION(CCalcDlg, "Button", Button, VT_BOOL, VTS_BSTR)
    //}}AFX_DISPATCH_MAP
END_DISPATCH_MAP()
 
#ifndef IMPLEMENT_OLECREATE_SINGLE
// MFC will provide this macro in the future.  For now, we define it.
#define IMPLEMENT_OLECREATE_SINGLE(class_name, external_name, 
    l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) 
    AFX_DATADEF COleObjectFactory class_name::factory(class_name::guid, 
        RUNTIME_CLASS(class_name), TRUE, _T(external_name)); 
    const AFX_DATADEF GUID class_name::guid = 
        { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } };
#endif
 
// {62C4DD10-F45E-11cd-8C3D-00AA004BB3B7}
IMPLEMENT_OLECREATE_SINGLE(CCalcDlg, "mfccalc.calculator", 
    0x62c4dd10, 0xf45e, 0x11cd, 0x8c, 0x3d, 0x0, 0xaa, 0x0, 0x4b, 0xb3, 0xb7);
 
CCalcDlg::CCalcDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CCalcDlg::IDD, pParent)
{
    //{{AFX_DATA_INIT(CCalcDlg)
        // NOTE: the ClassWizard will add member initialization here
    //}}AFX_DATA_INIT
    // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
 
    m_bAutoDelete = TRUE;   // default to auto-delete
    m_dwRegister = 0;       // not registered as active by default
 
    // Note that LoadAccelerator does not require DestroyAcceleratorTable
    m_hAccel = LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDD));
 
    // clear the contents of the calculator and reset state
    OnClickedClear();
 
    // enable this object for OLE automation
    EnableAutomation();
}   
 
CCalcDlg::~CCalcDlg()
{
    if (m_dwRegister != 0)
        RevokeActiveObject(m_dwRegister, NULL);
}
 
void CCalcDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CCalcDlg)
        // NOTE: the ClassWizard will add DDX and DDV calls here
    //}}AFX_DATA_MAP
}
 
/////////////////////////////////////////////////////////////////////////////
// CCalcDlg implementation
 
void CCalcDlg::PerformOperation()
{
    if (m_errorState != ErrNone)
        return;
 
    if (m_bOperandAvail)
    {
        if (m_operator == OpNone)
            m_accum = m_operand;
        else if (m_operator == OpMultiply)
            m_accum *= m_operand;
        else if (m_operator == OpDivide)
        {
            if (m_operand == 0)
                m_errorState = ErrDivideByZero;
            else
                m_accum /= m_operand;
        }
        else if (m_operator == OpAdd)
            m_accum += m_operand;
        else if (m_operator == OpSubtract)
            m_accum -= m_operand;
    }
 
    m_bOperandAvail = FALSE;
    UpdateDisplay();
}
 
void CCalcDlg::ClickedNumber(long l)
{
    if (m_errorState != ErrNone)
        return;
 
    if (!m_bOperandAvail)
        m_operand = 0L;
 
    SetOperand(m_operand*10+l);
    UpdateDisplay();
}
 
void CCalcDlg::UpdateDisplay()
{
    if (GetSafeHwnd() == NULL)
        return;
 
    CString str;
    if (m_errorState != ErrNone)
        str.LoadString(IDS_ERROR);
    else
    {
        long lVal = (m_bOperandAvail) ? m_operand : m_accum;
        str.Format(_T("%ld"), lVal);
    }
    GetDlgItem(IDE_ACCUM)->SetWindowText(str);
    GetDlgItem(IDC_INVISIBLE_FOCUS)->SetFocus();
}
 
BEGIN_MESSAGE_MAP(CCalcDlg, CDialog)
    //{{AFX_MSG_MAP(CCalcDlg)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_COMMAND_RANGE(IDB_0, IDB_9, OnClickedNumber)
    ON_BN_CLICKED(IDB_CLEAR, OnClickedClear)
    ON_BN_CLICKED(IDB_DIVIDE, OnClickedDivide)
    ON_BN_CLICKED(IDB_EQUAL, OnClickedEqual)
    ON_BN_CLICKED(IDB_MINUS, OnClickedMinus)
    ON_BN_CLICKED(IDB_PLUS, OnClickedPlus)
    ON_BN_CLICKED(IDB_TIMES, OnClickedTimes)
    ON_EN_SETFOCUS(IDE_ACCUM, OnSetFocusAccum)
    //}}AFX_MSG_MAP
#ifdef _MAC
    ON_BN_CLICKED(IDB_CLOSE, OnCancel)
#endif
END_MESSAGE_MAP()
 
/////////////////////////////////////////////////////////////////////////////
// CCalcDlg message handlers
 
BOOL CCalcDlg::OnInitDialog()
{
    CDialog::OnInitDialog();
 
    // Add "About..." menu item to system menu.
 
    // IDM_ABOUTBOX must be in the system command range.
    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX < 0xF000);
 
    CMenu* pSysMenu = GetSystemMenu(FALSE);
    CString strAboutMenu;
    strAboutMenu.LoadString(IDS_ABOUTBOX);
    if (!strAboutMenu.IsEmpty())
    {
#ifdef _MAC
        // On the Macintosh, the "About..." menu item is already there.  We
        //  just need to rename it and attach it to the about command.
        pSysMenu->ModifyMenu(0, MF_BYPOSITION, IDM_ABOUTBOX, strAboutMenu);
#else
        pSysMenu->AppendMenu(MF_SEPARATOR);
        pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
#endif
    }
 
#ifndef _MAC
    pSysMenu->RemoveMenu(SC_MAXIMIZE, MF_BYCOMMAND);
    pSysMenu->RemoveMenu(SC_SIZE, MF_BYCOMMAND);
#endif
    
    // want focus to stay on the dialog itself (until a button is clicked)
    SetFocus();
    return FALSE;  
}
 
void CCalcDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
    if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    {
        CAboutDlg dlgAbout;
        dlgAbout.DoModal();
    }
    else
    {
        CDialog::OnSysCommand(nID, lParam);
    }
}
 
// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.
 
void CCalcDlg::OnPaint() 
{
    if (!IsIconic())
    {
        CDialog::OnPaint();
        return;
    }
 
    CPaintDC dc(this); // device context for painting
 
    SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
 
    // Center icon in client rectangle
    int cxIcon = GetSystemMetrics(SM_CXICON);
    int cyIcon = GetSystemMetrics(SM_CYICON);
    CRect rect;
    GetClientRect(&rect);
    int x = (rect.Width() - cxIcon + 1) / 2;
    int y = (rect.Height() - cyIcon + 1) / 2;
 
    // Draw the icon
    dc.DrawIcon(x, y, m_hIcon);
}
 
// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CCalcDlg::OnQueryDragIcon()
{
    return (HCURSOR)m_hIcon;
}
 
void CCalcDlg::OnClickedNumber(UINT nID) 
{
    ASSERT(nID >= IDB_0 && nID <= IDB_9);
    ClickedNumber(nID - IDB_0);
}
 
void CCalcDlg::OnClickedClear() 
{
    m_operator = OpNone;
    m_operand = 0L;
    m_accum = 0L;
    m_bOperandAvail = FALSE;
    m_errorState = ErrNone;
    UpdateDisplay();
}
 
void CCalcDlg::OnClickedDivide() 
{
    PerformOperation();
    m_operator = OpDivide;
}
 
void CCalcDlg::OnClickedEqual() 
{
    PerformOperation();
    m_operator = OpNone;
}
 
void CCalcDlg::OnClickedMinus() 
{
    PerformOperation();
    m_operator = OpSubtract;
}
 
void CCalcDlg::OnClickedPlus() 
{
    PerformOperation();
    m_operator = OpAdd;
}
 
void CCalcDlg::OnClickedTimes() 
{
    PerformOperation();
    m_operator = OpMultiply;
}
 
BOOL CCalcDlg::PreTranslateMessage(MSG* pMsg) 
{
    if (m_hAccel != NULL && TranslateAccelerator(m_hWnd, m_hAccel, pMsg))
        return TRUE;
    
    return CDialog::PreTranslateMessage(pMsg);
}
 
void CCalcDlg::PostNcDestroy() 
{
    if (m_bAutoDelete)
        delete this;
}
 
void CCalcDlg::OnCancel()
{
    DestroyWindow();
}
 
void CCalcDlg::OnOK()
{
}
 
void CCalcDlg::OnSetFocusAccum() 
{
    GetDlgItem(IDC_INVISIBLE_FOCUS)->SetFocus();
}
 
/////////////////////////////////////////////////////////////////////////////
// CCalcDlg automation
 
BOOL CCalcDlg::RegisterActive()
{
    // attempt to register as the active object for the CCalcDlg CLSID
    return RegisterActiveObject(GetInterface(&IID_IUnknown), 
        CCalcDlg::guid, NULL, &m_dwRegister) == NOERROR;
}
 
long CCalcDlg::GetAccum() 
{
    return m_accum;
}
 
void CCalcDlg::SetAccum(long nNewValue) 
{
    m_accum = nNewValue;
}
 
long CCalcDlg::GetOperand() 
{
    return m_operand;
}
 
void CCalcDlg::SetOperand(long nNewValue) 
{
    m_operand = nNewValue;
    m_bOperandAvail = TRUE;
}
 
short CCalcDlg::GetOperation() 
{
    return m_operator;
}
 
void CCalcDlg::SetOperation(short nNewValue) 
{
    m_operator = (Operator)nNewValue;
}
 
BOOL CCalcDlg::GetVisible() 
{
    return m_hWnd != NULL && (GetStyle() & WS_VISIBLE) != 0;
}
 
void CCalcDlg::SetVisible(BOOL bNewValue) 
{
    if (bNewValue == GetVisible())
        return;
 
    if (bNewValue)
    {
        // create it if necessary
        if (m_hWnd == NULL && !Create(CCalcDlg::IDD))
            return;
 
        // set up as the active window for the application
        if (AfxGetThread()->m_pMainWnd == NULL)
            AfxGetThread()->m_pMainWnd = this;
 
        // show it
        ShowWindow(SW_SHOWNORMAL);
    }
    else
    {
        if (m_hWnd != NULL)
            ShowWindow(SW_HIDE);
    }
}
 
BOOL CCalcDlg::Evaluate() 
{
    OnClickedEqual();
    return m_errorState == ErrNone;
}
 
void CCalcDlg::Clear() 
{
    OnClickedClear();
}
 
void CCalcDlg::Display() 
{
    UpdateDisplay();
}
 
void CCalcDlg::Close() 
{
    if (m_hWnd == NULL)
    {
        AfxPostQuitMessage(0);
        return;
    }
 
    BOOL bAutoDelete = m_bAutoDelete;
    m_bAutoDelete = FALSE;
    DestroyWindow();
    m_bAutoDelete = bAutoDelete;
}
 
BOOL CCalcDlg::Button(LPCTSTR szButton) 
{
    switch (szButton[0])
    {
    case 'c':
    case 'C':
        OnClickedClear();
        break;
 
    case '/':
        OnClickedDivide();
        break;
    case '+':
        OnClickedPlus();
        break;
    case '-':
        OnClickedMinus();
        break;
    case '*':
        OnClickedTimes();
        break;
    case '=':
        OnClickedEqual();
        break;
 
    default:
        if (szButton[0] >= '0' && szButton[0] <= '9')
            ClickedNumber(szButton[0] - '0');
        else
            return FALSE;
        break;
    }
    return TRUE;
}

Одна из задач, задаваемых студентам по программированию, это создание калькулятора. Раскрою вам небольшой секрет: немало практических, курсовых и лабораторных работ на C++, C# и Java можно и не делать самостоятельно – есть готовые решения в сети. Однако, я был несколько удивлен, что для такого распространенного задания, как визуальный калькулятор на C++ нет такого готового решения. Ну что ж, нет, так нет, давайте напишем его сами.

Итак, как в большинстве проектов, все начинается с создания приложения Windows Forms, а уже в нем – с редактирования формы. У нас получилась вот такая:


Проект для VS2015

В чем будем считать и хранить числа? Я выбрал тип double – точности его нам вполне хватит; это все же студенческая работа, а не для точных инженерных расчетов. Дальше определимся с тем, сколько чисел и операций будем хранить в памяти. Предположим, штук двадцать: тогда надо создать два массива – один для чисел, а другой для операций между ними.

static array<double> ^mass = gcnew array<double>{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
static array<int> ^ukaz = gcnew array<int>{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

Почему мы воспользовались указателями, а не просто создали глобальные переменные за пределами windows forms? Дело в том, что, использование глобальных переменных – это плохой тон при программировании, и очень часто преподаватели против данной практики студентов.

В нашей программе будут три основных метода: vvod — принимает цифру (нажатую кнопку) в качестве аргумента и добавляет её к числу. ravno — нажатие на кнопку равно — все считает, ravno2 — это нажатие на кнопку знака. Факториал, деление единицы на число и корень квадратные — там реализуются методы сразу при нажатии все обрабатывается.

Добавим также флаг для памяти:

static int mem_flag=0;

И еще систему флагов:

//переменные для памяти
static double memory_znachenie = 0.0;
static int memory_status = 0;
//предыдущая клавиша
static int pred_klav = 0;
static int flag_ravno = 0;
static int put = 0;

Вот, например, как у нас будет выглядеть метод vvod():

//ввод цифр на экран
private: System::Void	vvod (double pr) {         
if (pred_klav==0) {
String^ s = textBox1->Text;
int dl = s->Length;
if (dl<10) {
String^ st = s + Convert::ToString(pr);
textBox1->Text = st;
mass[mem_flag] = Convert::ToDouble(textBox1->Text);
textBox1->Text = Convert::ToString(mass[mem_flag]);
pred_klav = 0;
}
}
else {
String^ st = Convert::ToString(pr);
textBox1->Text = st;
mass[mem_flag] = Convert::ToDouble(textBox1->Text);
textBox1->Text = Convert::ToString(mass[mem_flag]);
pred_klav = 0;
}
}

Здесь мы проверяем, какая клавиша в нашем калькуляторе была нажата перед этим – цифра, арифметическая операция или знак равно. Далее получаем из текстбокса значение, конвертируем предыдущее из массива, конкатенируем строки, потом обратно в double и обновляем значение массива. Также в этом методе мы проверяем длину числа – мы поставили ограничение на 10 знаков.

Обработка кнопки равно – то есть метод вычисления – также не представляет сложности. Пользуясь оператором ветвления switch перебираем все варианты.

Также реализуем собственный класс для обработки ошибок. Зачем это надо? Дело в том, что мы оперируем с числами типа double, а они не выбрасывают некоторые стандартные исключения, например – деление на ноль. Также мы предусмотрим обработку переполнения и вычисления квадратного корня из отрицательного числа. На вход конструкторов этого класса будем принимать пару чисел. Выводятся ошибки при:

  1. взятии корня четной степени из отрицательного числа
  2. логарифмировании отрицательного числа и нуля
  3. делении на нуль.
  4. переполнении (калькулятор все же не бесконечный)

Также не забудем и обработку клавиши запятой. Для этого проверяем, есть ли она уже во введённом числе:

MarshalString(s, s2);
int pos = s2.find(",") ;
if (pos==-1) { }

Вот такие основные моменты надо знать для написания данной программы. Ну а если вы не можете самостоятельно написать визуальный калькулятор на C++, то обратитесь ко мне. Актуальную цену за архив с готовой программой и исходниками с подробными комментариями в настоящий моент 500 рублей. Это будет проект в Visual Studio C++ 2010 — он откроется в любой другой версии студии не ниже 2010. Также есть проект для Visual Studio 2015.

Мой калькулятор реализует все основные функции: сложение, вычитание, деление, умножение, факториал, возведение в степень, извлечение квадратного корня, вычисление 1/x, функции памяти (занести в память, вывести содержимое памяти, очистить память).

Обновление

Добавились новые функции в калькуляторе. А именно:

  • Извлечение корня четной и нечетной степени из числа
  • Вычисление логарифма по любому основанию
  • Вычисление экспоненты

Если вам требуется реализация других функций, то это делается за отдельную плату. Пишите на почту up777up@yandex.ru, стучитесь vk.com/idup7, @upreadru или по другим контактам.


Автор этого материала — я — Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML — то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.

тегистатьи IT, си плюс плюс, visual studio, калькулятор

Читайте также:

  • Морской бой на Java с исходниками

Today let’s work around a new interesting visual C++ (cpp) calculator with Graphical User Interface (Windows Form Application). I made this source as easier as possible. You can compile the source by downloading the project source from below.

Why is it simple calculator? It has only the basic functions of a calculator such as addition, subtraction, multiplication,division and 2 others. First Entered number is taken to the first variable a. Then select and operator, enter the second number. Do the necessary operations and When you press “=” equals button, you can see the answer right where you expect it.

More than these basic operations, you can also find the square and square root of a number. I have added buttons for this. This program make use of “math.h” which contains “sqrt()” and “power()” functions for accomplishing these tasks.

Visual Cpp Calculator

Let me know your feedback in the comments.

Use visual c++ 2010 compiler for execution.

                                               Download Calculator Visual C++ Project

Source……………………………Form1.h[design]

 #pragma once  
 #include<conio.h> //For_getch()_function  
 #include<math.h>  
 double ans, a, b;  
 int flag=0;  
 using namespace std;  
 namespace Calculator {  
     using namespace System;  
     using namespace System::ComponentModel;  
     using namespace System::Collections;  
     using namespace System::Windows::Forms;  
     using namespace System::Data;  
     using namespace System::Drawing;  
     /// <summary>  
     /// Summary for Form1  
     /// </summary>  
     public ref class Form1 : public System::Windows::Forms::Form  
     {  
     public:  
        Form1(void)  
        {  
            InitializeComponent();  
            //  
            //TODO: Add the constructor code here  
            //  
        }  
     protected:  
        /// <summary>  
        /// Clean up any resources being used.  
        /// </summary>  
        ~Form1()  
        {  
            if (components)  
            {  
               delete components;  
            }  
        }  
     private: System::Windows::Forms::TextBox^ txtb;  
     private: System::Windows::Forms::Button^ button1;  
     private: System::Windows::Forms::Button^ button2;  
     private: System::Windows::Forms::Button^ button3;  
     private: System::Windows::Forms::Button^ button4;  
     private: System::Windows::Forms::Button^ button5;  
     private: System::Windows::Forms::Button^ button6;  
     private: System::Windows::Forms::Button^ button7;  
     private: System::Windows::Forms::Label^ label1;  
     private: System::Windows::Forms::MenuStrip^ menuStrip1;  
     private: System::Windows::Forms::ToolStripMenuItem^ menuToolStripMenuItem;  
     private: System::Windows::Forms::ToolStripMenuItem^ exitToolStripMenuItem;  
     protected:  
     protected:  
     protected:  
     private:  
        /// <summary>  
        /// Required designer variable.  
        /// </summary>  
        System::ComponentModel::Container ^components;  
 #pragma region Windows Form Designer generated code  
        /// <summary>  
        /// Required method for Designer support - do not modify  
        /// the contents of this method with the code editor.  
        /// </summary>  
        void InitializeComponent(void)  
        {  
            System::ComponentModel::ComponentResourceManager^ resources = (gcnew System::ComponentModel::ComponentResourceManager(Form1::typeid));  
            this->txtb = (gcnew System::Windows::Forms::TextBox());  
            this->button1 = (gcnew System::Windows::Forms::Button());  
            this->button2 = (gcnew System::Windows::Forms::Button());  
            this->button3 = (gcnew System::Windows::Forms::Button());  
            this->button4 = (gcnew System::Windows::Forms::Button());  
            this->button5 = (gcnew System::Windows::Forms::Button());  
            this->button6 = (gcnew System::Windows::Forms::Button());  
            this->button7 = (gcnew System::Windows::Forms::Button());  
            this->label1 = (gcnew System::Windows::Forms::Label());  
            this->menuStrip1 = (gcnew System::Windows::Forms::MenuStrip());  
            this->menuToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem());  
            this->exitToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem());  
            this->menuStrip1->SuspendLayout();  
            this->SuspendLayout();  
            //  
            // txtb  
            //  
            this->txtb->BackColor = System::Drawing::Color::White;  
            this->txtb->BorderStyle = System::Windows::Forms::BorderStyle::FixedSingle;  
            this->txtb->Font = (gcnew System::Drawing::Font(L"Arial Rounded MT Bold", 26.25F, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point,  
               static_cast<System::Byte>(0)));  
            this->txtb->ForeColor = System::Drawing::Color::Black;  
            this->txtb->Location = System::Drawing::Point(32, 44);  
            this->txtb->Margin = System::Windows::Forms::Padding(2, 3, 2, 3);  
            this->txtb->Name = L"txtb";  
            this->txtb->Size = System::Drawing::Size(300, 48);  
            this->txtb->TabIndex = 0;  
            this->txtb->TextAlign = System::Windows::Forms::HorizontalAlignment::Right;  
            this->txtb->WordWrap = false;  
            this->txtb->TextChanged += gcnew System::EventHandler(this, &Form1::txtb_TextChanged);  
            //  
            // button1  
            //  
            this->button1->Font = (gcnew System::Drawing::Font(L"Arial Rounded MT Bold", 27.75F, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point,  
               static_cast<System::Byte>(0)));  
            this->button1->Location = System::Drawing::Point(32, 108);  
            this->button1->Margin = System::Windows::Forms::Padding(2, 3, 2, 3);  
            this->button1->Name = L"button1";  
            this->button1->Size = System::Drawing::Size(98, 49);  
            this->button1->TabIndex = 1;  
            this->button1->Text = L"+";  
            this->button1->UseVisualStyleBackColor = true;  
            this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click);  
            //  
            // button2  
            //  
            this->button2->Font = (gcnew System::Drawing::Font(L"Letterman-Solid", 15.75F, System::Drawing::FontStyle::Italic, System::Drawing::GraphicsUnit::Point,  
               static_cast<System::Byte>(0)));  
            this->button2->Location = System::Drawing::Point(234, 108);  
            this->button2->Margin = System::Windows::Forms::Padding(2, 3, 2, 3);  
            this->button2->Name = L"button2";  
            this->button2->Size = System::Drawing::Size(98, 49);  
            this->button2->TabIndex = 2;  
            this->button2->Text = L"=";  
            this->button2->UseVisualStyleBackColor = true;  
            this->button2->Click += gcnew System::EventHandler(this, &Form1::button2_Click);  
            //  
            // button3  
            //  
            this->button3->Font = (gcnew System::Drawing::Font(L"Arial Rounded MT Bold", 27.75F, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point,  
               static_cast<System::Byte>(0)));  
            this->button3->Location = System::Drawing::Point(32, 160);  
            this->button3->Margin = System::Windows::Forms::Padding(2, 3, 2, 3);  
            this->button3->Name = L"button3";  
            this->button3->Size = System::Drawing::Size(98, 49);  
            this->button3->TabIndex = 3;  
            this->button3->Text = L"-";  
            this->button3->UseVisualStyleBackColor = true;  
            this->button3->Click += gcnew System::EventHandler(this, &Form1::button3_Click);  
            //  
            // button4  
            //  
            this->button4->Font = (gcnew System::Drawing::Font(L"Arial Rounded MT Bold", 27.75F, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point,  
               static_cast<System::Byte>(0)));  
            this->button4->Location = System::Drawing::Point(32, 212);  
            this->button4->Margin = System::Windows::Forms::Padding(2, 3, 2, 3);  
            this->button4->Name = L"button4";  
            this->button4->Size = System::Drawing::Size(98, 49);  
            this->button4->TabIndex = 4;  
            this->button4->Text = L"x";  
            this->button4->UseVisualStyleBackColor = true;  
            this->button4->Click += gcnew System::EventHandler(this, &Form1::button4_Click);  
            //  
            // button5  
            //  
            this->button5->Font = (gcnew System::Drawing::Font(L"Arial Rounded MT Bold", 27.75F, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point,  
               static_cast<System::Byte>(0)));  
            this->button5->Location = System::Drawing::Point(32, 264);  
            this->button5->Margin = System::Windows::Forms::Padding(2, 3, 2, 3);  
            this->button5->Name = L"button5";  
            this->button5->Size = System::Drawing::Size(98, 49);  
            this->button5->TabIndex = 5;  
            this->button5->Text = L"/";  
            this->button5->UseVisualStyleBackColor = true;  
            this->button5->Click += gcnew System::EventHandler(this, &Form1::button5_Click);  
            //  
            // button6  
            //  
            this->button6->Font = (gcnew System::Drawing::Font(L"Arial Rounded MT Bold", 12, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point,  
               static_cast<System::Byte>(0)));  
            this->button6->Location = System::Drawing::Point(234, 161);  
            this->button6->Margin = System::Windows::Forms::Padding(2, 3, 2, 3);  
            this->button6->Name = L"button6";  
            this->button6->Size = System::Drawing::Size(98, 49);  
            this->button6->TabIndex = 6;  
            this->button6->Text = L"ROOT";  
            this->button6->UseVisualStyleBackColor = true;  
            this->button6->Click += gcnew System::EventHandler(this, &Form1::button6_Click);  
            //  
            // button7  
            //  
            this->button7->Font = (gcnew System::Drawing::Font(L"Arial Rounded MT Bold", 12, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point,  
               static_cast<System::Byte>(0)));  
            this->button7->Location = System::Drawing::Point(234, 212);  
            this->button7->Margin = System::Windows::Forms::Padding(2, 3, 2, 3);  
            this->button7->Name = L"button7";  
            this->button7->Size = System::Drawing::Size(98, 49);  
            this->button7->TabIndex = 7;  
            this->button7->Text = L"SQUARE";  
            this->button7->UseVisualStyleBackColor = true;  
            this->button7->Click += gcnew System::EventHandler(this, &Form1::button7_Click);  
            //  
            // label1  
            //  
            this->label1->AutoSize = true;  
            this->label1->BackColor = System::Drawing::SystemColors::HighlightText;  
            this->label1->Font = (gcnew System::Drawing::Font(L"KabobExtrabold", 12, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point,  
               static_cast<System::Byte>(0)));  
            this->label1->Location = System::Drawing::Point(123, 3);  
            this->label1->Name = L"label1";  
            this->label1->Size = System::Drawing::Size(135, 18);  
            this->label1->TabIndex = 8;  
            this->label1->Text = L"Simple Calculator";  
            this->label1->Click += gcnew System::EventHandler(this, &Form1::label1_Click);  
            //  
            // menuStrip1  
            //  
            this->menuStrip1->Items->AddRange(gcnew cli::array< System::Windows::Forms::ToolStripItem^ >(1) {this->menuToolStripMenuItem});  
            this->menuStrip1->LayoutStyle = System::Windows::Forms::ToolStripLayoutStyle::Flow;  
            this->menuStrip1->Location = System::Drawing::Point(0, 0);  
            this->menuStrip1->Name = L"menuStrip1";  
            this->menuStrip1->Size = System::Drawing::Size(360, 23);  
            this->menuStrip1->TabIndex = 10;  
            this->menuStrip1->Text = L"menuStrip1";  
            this->menuStrip1->ItemClicked += gcnew System::Windows::Forms::ToolStripItemClickedEventHandler(this, &Form1::menuStrip1_ItemClicked);  
            //  
            // menuToolStripMenuItem  
            //  
            this->menuToolStripMenuItem->DropDownItems->AddRange(gcnew cli::array< System::Windows::Forms::ToolStripItem^ >(1) {this->exitToolStripMenuItem});  
            this->menuToolStripMenuItem->Name = L"menuToolStripMenuItem";  
            this->menuToolStripMenuItem->Size = System::Drawing::Size(50, 19);  
            this->menuToolStripMenuItem->Text = L"Menu";  
            this->menuToolStripMenuItem->Click += gcnew System::EventHandler(this, &Form1::menuToolStripMenuItem_Click);  
            //  
            // exitToolStripMenuItem  
            //  
            this->exitToolStripMenuItem->Name = L"exitToolStripMenuItem";  
            this->exitToolStripMenuItem->Size = System::Drawing::Size(92, 22);  
            this->exitToolStripMenuItem->Text = L"Exit";  
            this->exitToolStripMenuItem->Click += gcnew System::EventHandler(this, &Form1::exitToolStripMenuItem_Click);  
            //  
            // Form1  
            //  
            this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);  
            this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;  
            this->BackgroundImage = (cli::safe_cast<System::Drawing::Image^ >(resources->GetObject(L"$this.BackgroundImage")));  
            this->BackgroundImageLayout = System::Windows::Forms::ImageLayout::Stretch;  
            this->ClientSize = System::Drawing::Size(360, 324);  
            this->Controls->Add(this->label1);  
            this->Controls->Add(this->button7);  
            this->Controls->Add(this->button6);  
            this->Controls->Add(this->button5);  
            this->Controls->Add(this->button4);  
            this->Controls->Add(this->button3);  
            this->Controls->Add(this->button2);  
            this->Controls->Add(this->button1);  
            this->Controls->Add(this->txtb);  
            this->Controls->Add(this->menuStrip1);  
            this->DoubleBuffered = true;  
            this->Font = (gcnew System::Drawing::Font(L"Microsoft Sans Serif", 8.25F, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point,  
               static_cast<System::Byte>(0)));  
            this->ForeColor = System::Drawing::Color::Black;  
            this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::Fixed3D;  
            this->MainMenuStrip = this->menuStrip1;  
            this->Margin = System::Windows::Forms::Padding(2, 3, 2, 3);  
            this->Name = L"Form1";  
            this->Text = L"Form1";  
            this->Load += gcnew System::EventHandler(this, &Form1::Form1_Load);  
            this->menuStrip1->ResumeLayout(false);  
            this->menuStrip1->PerformLayout();  
            this->ResumeLayout(false);  
            this->PerformLayout();  
        }  
 #pragma endregion  
     private: System::Void txtb_TextChanged(System::Object^ sender, System::EventArgs^ e) {  
               int temp;  
                      if(Int32::TryParse(txtb->Text, temp))  
                 a = float::Parse(txtb->Text);  
            }  
     private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {  
               flag=1;  
               b = double::Parse(txtb->Text);  
               ans=a+b;  
            }  
 private: System::Void button3_Click(System::Object^ sender, System::EventArgs^ e) {  
            flag=2;  
             b = float::Parse(txtb->Text);  
         }  
     private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) {  
               if(a==0 && b==0)  
               {  
                   txtb->Text = "Enter Numbers";  
               }  
               if(flag==1)  
               {  
               ans=a+b;  
                   txtb->Text = Convert::ToString(ans);  
               }  
               else if(flag==2)  
               {  
                  ans=b-a;  
                  txtb->Text = Convert::ToString(ans);  
               }  
               else if(flag==3)  
               {  
                  ans=b*a;  
                  txtb->Text = Convert::ToString(ans);  
               }  
               else if(flag==4)  
               {  
                  if(a==0)  
                  {  
                      MessageBox::Show("Divided By Zero Error");  
                  }  
                  ans=b/a;  
                  txtb->Text = Convert::ToString(ans);  
               }  
            }  
 private: System::Void button4_Click(System::Object^ sender, System::EventArgs^ e) {  
            flag=3;  
             b = double::Parse(txtb->Text);  
         }  
 private: System::Void button5_Click(System::Object^ sender, System::EventArgs^ e) {  
            flag=4;  
            b = double::Parse(txtb->Text);  
         }  
 private: System::Void button6_Click(System::Object^ sender, System::EventArgs^ e) {  
            ans=sqrt(a);  
            txtb->Text = Convert::ToString(ans);  
         }  
 private: System::Void button7_Click(System::Object^ sender, System::EventArgs^ e) {  
         ans=a*a;  
            txtb->Text = Convert::ToString(ans);  
         }  
 private: System::Void label1_Click(System::Object^ sender, System::EventArgs^ e) {  
            MessageBox::Show("Created By :nn Muhammed Afsal.vn e-mail : [email protected]");  
         }  
 private: System::Void button8_Click(System::Object^ sender, System::EventArgs^ e) {  
            a=b=0;  
         }  
 private: System::Void exitToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) {  
            Application::Exit();  
         }  
 private: System::Void menuStrip1_ItemClicked(System::Object^ sender, System::Windows::Forms::ToolStripItemClickedEventArgs^ e) {  
         }  
 private: System::Void menuToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) {  
         }  
 private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) {  
         }  
 };  
 }  

———————————-Calculator.cpp

// Calculator.cpp : main project file.  
 #include "stdafx.h"  
 #include "Form1.h"  
 using namespace Calculator;  
 [STAThreadAttribute]  
 int main(array<System::String ^> ^args)  
 {  
     // Enabling Windows XP visual effects before any controls are created  
     Application::EnableVisualStyles();  
     Application::SetCompatibleTextRenderingDefault(false);  
     // Create the main window and run it  
     Application::Run(gcnew Form1());  
     return 0;  
 }  

 ———————————————————————————————————-

Screen Shots :-

Screen_Shot_2

Создаем исходный код программы-калькулятора в Windows Forms на языке программирования C#.

Также имеется разбор более усовершенствованного калькулятора здесь и простой консольный калькулятор вот здесь.

Для начала нам надо расположить все нужные элементы на форме. Нам понадобятся три TextBox’a и 6 кнопок-Button. Устанавливаем их вот таким образом и переименовываем кнопки в свойствах:

Простенький калькулятор Windows Forms на C# - vscode.ru

Наш калькулятор основан на взаимодействии двух чисел, поэтому математические операции будут следующие:

  • Сложение
  • Вычитание
  • Умножение
  • Деление
  • Возведение первого числа в степень второго
  • Взятие корня первого числа степени второго числа.

Итак, после того, как с графическим оформлением закончено, приступаем к самому коду.

Для всех вышеописанных операций мы создадим отдельные функции. Функции — это, так сказать, подпрограммы в самой программе, выполняющие отдельные задачи. Они помогают сократить и облегчить код.

Вот так у нас будет выглядеть функция сложения:

public static double sum(double a, double b)

        {

            return a + b;

        }

Разберем этот код по частям:

Для начала мы объявляем программе, что создаем функцию (пишем public static), затем определяем тип функции(double — числовой тип повышенной точности с плавающей запятой, лучший вариант), после даём имя функции(sum) и в скобках записываем то, что, так сказать, получает функция от программы( double a и double b — первое и второе числа, которые мы запишем в первые два TextBox’a). Выражение return возвращает в функцию результат сложения a и b. То есть наша функция получает два числа от пользователя, который введет их в форме и, при помощи return’a, в неё же заносится результат вычисления.

Точно так же создаём функции остальных математических выражений:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

  public static double razn(double a, double b)

        {

            return a b;

        }

  public static double umnog(double a, double b)

        {

            return a * b;

        }

  public static double del(double a, double b)

        {

            return a / b;

        }

  public static double step(double a, double b)

        {

            return Math.Pow(a, b);

        }

  public static double koren(double a, double b)

        {

            return Math.Pow(a, 1/b);

        }

Функции созданы, сталось лишь привязать их к кнопкам в форме. Дважды щёлкаем мышью в форме на первую кнопку. Нас переносит в часть кода, которая отвечает за событие, которое произойдет, когда пользователь кликнет на данную кнопку. В теле этого события мы пишем:

private void button1_Click(object sender, EventArgs e)

        {

            textBox3.Text = Convert.ToString(sum(Convert.ToDouble(textBox1.Text), Convert.ToDouble(textBox2.Text)));

        }

Разбор кода начнём, как ни странно, с конца. Мы помним, что при объявлении функции мы писали вот такую часть кода: sum(double a, double b). То есть функция может получить только значения типа double. Также мы помним, что эти значения мы получаем от пользователя, который, в свою очередь, вводит их в первый и второй TextBox’ы. Однако проблема в том, что значения из TextBox’ов воспринимаются программой как строки, то есть типом string. Поэтому их надо конвертировать в нужный нам double, что мы и делаем: sum(Convert.ToDouble(textBox1.Text), Convert.ToDouble(textBox2.Text))

Значения переведены, сумма посчитана. Осталось вывести её в TextBox3. Однако, у нас опять проблемы с типами. Наша посчитанная сумма принадлежит типу double, а TextBox принимает только string. Конвертируем sum в string и записываем её в TextBox3 как строку.
То же самое проделываем с остальными кнопками и функциями:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

        private void button2_Click(object sender, EventArgs e)

        {

            textBox3.Text = Convert.ToString(razn(Convert.ToDouble(textBox1.Text), Convert.ToDouble(textBox2.Text)));

        }

        private void button3_Click(object sender, EventArgs e)

        {

            textBox3.Text = Convert.ToString(umnog(Convert.ToDouble(textBox1.Text), Convert.ToDouble(textBox2.Text)));

        }

        private void button4_Click(object sender, EventArgs e)

        {

            textBox3.Text = Convert.ToString(del(Convert.ToDouble(textBox1.Text), Convert.ToDouble(textBox2.Text)));

        }

        private void button5_Click(object sender, EventArgs e)

        {

            textBox3.Text = Convert.ToString(step(Convert.ToDouble(textBox1.Text), Convert.ToDouble(textBox2.Text)));

        }

        private void button6_Click(object sender, EventArgs e)

        {

            textBox3.Text = Convert.ToString(koren(Convert.ToDouble(textBox1.Text), Convert.ToDouble(textBox2.Text)));

        }

Вот и всё. Наш калькулятор готов!

Простенький калькулятор Windows Forms на C# - vscode.ru

Исходный код калькулятора:

Скачать исходник

Понравилась статья? Поделить с друзьями:
  • Разрешенные угрозы windows 10 не удаляются
  • Разогнать компьютер windows 10 через bios
  • Разный фон рабочего стола на двух мониторах windows 10
  • Разрешенные угрозы windows 10 как удалить
  • Разрешенные символы в имени файла windows