各位朋友若覺得本教學對您有幫助,請點個讚~
※ 以下範例均使用dev-C++(免費,可自行google下載)中,「專案」內的Console Application來撰寫,如下圖:
(1)
(2)
※ 以下文字中,黑色文字是說明,淺藍色文字代表程式碼,紫色文字代表程式之輸出結果。
※ 選擇Console Application之後,dev-C++會自動產生下列程式碼:
#include <cstdlib>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
system("PAUSE");
return EXIT_SUCCESS;
}
以上的main是主程式名稱,故以下本教學所使用的所有程式碼皆是寫在兩個大括號 { 和 } 之間、system("PAUSE"); 之前。
1. 基礎語法:
(1) 斷行:
每行C++程式碼,在行尾要加個分號 ;。
(2) 變數宣告:
變數宣告利用到等號 =,其基本語法為:
變數型態 變數名稱 = 值;
※ 其中,常用的變數形態介紹如下:
|
變數形態 |
值的說明 |
|
bool |
這種變數形態叫做「布林變數」,其值只有兩種可能,true和false。true表示邏輯上的「真」,false表示邏輯上的「假」。 |
|
int |
這種變數形態叫做「整數」,其值如:-2, -1, 0, 1, 2, 3, 4 …… |
|
float |
這種變數形態叫做「浮點數」,即是帶有小數點的數字。其值如:-2.3321, 0, 1.0, 2623.292 …… |
|
double |
這種變數形態叫做「雙精度浮點數」,和float一樣是帶有小數點的數字,不過比float更佔記憶空間。其值如:-2.3321, 0, 1.0, 2623.292 …… |
|
char |
這種變數形態叫做「字元」,也就是文字,可以是英文、中文、數字…等等。字元的左右兩邊需要用單引號 ' 包起來,如 '大','a','1'。 |
|
string |
這種變數形態叫做「字串」,也就是一連串的文字,可以是英文、中文、數字…等等。字串的左右兩邊需要用雙引號 " 包起來,如 "大小你我他","abcde","12345"。 |
※ 變數名稱:一個由程式設計師自訂的名稱。但要注意,變數名稱只能是英文、
數字或底線符號 _,且開頭第一個字母一定要是英文,否則編譯軟體無法辨識。
※ 值:該變數的值,和變數型態有關。
變數宣告的範例如:
string name = "白龍馬";
int money = 20000;
bool is_white = true;
其中,name、money、is_white都是變數名稱。
※ 變數的宣告,事實上是在電腦中安排一記憶體空間來存放值。而不同的變數型態所佔的記憶體空間也是不同的。
(3) 註解:
單行註解可用雙斜線//,如:
// 註解ABCD
多行註解可用雙斜線/與星號*搭配,如:
/*
這是註解一
這是註解二
*/
這些被註解的文字是不會被執行的,且註解可用中文。程式設計師寫註解的目的在於提醒自己這一行、或這一段程式碼是寫來幹嘛的,以免過幾天再看自己寫的程式碼,忘了自己為何要這樣寫。
(4) 基本輸出:
※ 可使用cout<<變數名稱或值來進行基本輸出,然後會在螢幕上顯示。如:
string B= "蘋果";
cout<<B;
執行後螢幕上顯示:蘋果
(dev-C++的輸出螢幕最後方可能會出現:請按任意鍵繼續,不必理他)
※ 此外,上述的cout方法也支持多變數連續輸出,如:
string A = "我買了";
int number = 5;
string B= "蘋果";
cout<<A<<number<<B;
執行後螢幕上顯示:我買了5蘋果
※ 斷行:
若想輸出到下一行,可用cout<<endl; 如:
cout<<"我是第一行"<<endl;
cout<<"我是第二行"<<endl;
cout<<"我是第三行"<<endl;
執行後螢幕上顯示:
我是第一行
我是第二行
我是第三行
(5) 基本輸入:
※ 可使用cin>>變數名稱來使用鍵盤輸入為該變數輸入值。執行後螢幕會停留、等待使用者用鍵盤輸入,輸入完畢會再繼續執行。範例如:
int n;
cout<<"你買了幾顆蘋果?"<<endl;
cin>>n;
cout<<"我買了"<<n<<"顆蘋果"<<endl;
執行後,螢幕停留在:
用鍵盤隨便輸入一個數字,譬如3,之後按下enter,螢幕顯示:

老師好 我又來想請教兩個問題 目前我用dev c++ 寫視窗程式..已經可以打英文字母與數字了 概略如下 case WM_KEYDOWN: hdc = GetDC(hwnd); szasciibuf=MapVirtualKey(wParam,0); itoa(szasciibuf, szbuf,10); TextOut(hdc,30,30,szbuf,lstrlen(szbuf)); szdecbuf=MapVirtualKey(wParam,2); // 2 itoa(szdecbuf, szdectextoutbuf,10); // 2:二進制. 10:十進制. 16:十六進制 TextOut(hdc,30,50,szdectextoutbuf,lstrlen(szdectextoutbuf)); ReleaseDC(hwnd,hdc); return 0; case WM_CHAR: wsprintf(szchar, "%c", wParam); GetCaretPos(&ptcaretpos); DestroyCaret(); if(szdecbuf == 8) // BackSpace { wsprintf(szchar, "%c", 32); ptcaretpos.x = ptcaretpos.x - 8 - nadjust ; TextOut(GetDC(hwnd), ptcaretpos.x, ptcaretpos.y-18,szchar,lstrlen(szchar)); ptcaretpos.x = ptcaretpos.x - 10; }; if(szdecbuf != 8 ) // BackSpace if(szdecbuf != 13) // Enter TextOut(GetDC(hwnd), ptcaretpos.x, ptcaretpos.y-14,szchar,lstrlen(szchar)); else { ptcaretpos.x = 0; ptcaretpos.y = ptcaretpos.y + 18; }; CreateCaret(hwnd, NULL, 10,1); ShowCaret(hwnd); SetCaretPos(ptcaretpos.x+10, ptcaretpos.y); return 0; 但就是沒辦法打中文 能不能教一下怎麼打中文字 最好能有程式碼... 因為看了很多介紹 ASCII碼..Unicode碼...UTF-8 等等 就是看不懂怎麼用到 c++ 來 另外 cin>>n; cin>>s; 在視窗程式中要寫在哪個地方 又要怎麼寫 能否指導一下.... 感激不盡~~
你好 你的方法看來是直接偵測鍵盤按鍵,然後輸出你偵測的結果 我先請問,你想要做的,是單純獲取輸入、然後輸出嗎?
應該這麼說吧 以前我們用 cin>> 來取的ˊ輸入文字(中英文)或數字資料 當然在輸入過程當中..我們打了甚麼資料也要在螢幕上顯示 這樣才知道有沒有打錯資料 我最主要的是要取得輸入的文字(中英文)或數字的資料 顯示在螢幕上是為了確認輸入正確否 而輸入後就可以做一些我想要的處理 至於要輸出的用 TextOut() 可以處理 但要輸入卻也不知道要到哪個視窗訊息鋪排 (這是第二個問題) 以上 謝謝~~
學習視窗程式 應要認識幾個基本元件,如按鈕(button)、文字區塊(edit)...等 介面上的輸入、輸出、控制,都是透過這幾個基本元件(與cin、cout無關) 以下的範例,我用按鈕、文字區塊來進行輸入與輸出 你用dev新開一個windows appplication,然後, 1. 以下這一行放在LRESULT CALLBACK WndProc之前: HWND handle; 2. 以下這一段程式碼放在 LRESULT CALLBACK WndProc的switch(Message) { 之內: case WM_CREATE: { handle=CreateWindow(TEXT("edit"),TEXT("請在這裡打字"),WS_VISIBLE | WS_CHILD, 10, 10, 100, 50, hwnd, (HMENU) 1, NULL, NULL); CreateWindow(TEXT("button"),TEXT("打字完按我"),WS_VISIBLE | WS_CHILD, 10, 110, 100, 50, hwnd, (HMENU) 1, NULL, NULL); break; } case WM_COMMAND:{ switch (HIWORD(wParam)) { case BN_CLICKED:{ char buffer[256] = {0}; GetWindowTextA(handle,buffer,256); MessageBox(NULL, buffer ,"您輸入的是:", MB_OK); break; } default: break; } break; } 接著執行,看看是不是你要的功能
感激不盡~~ 一開始我也是從文字區塊(edit)下手 我是在GetWindowTextA( )一直取值失敗後才改思考方向 想說不然直接在畫面上做輸入 這樣差不多是我想要的 不過還有兩個問題請教一下 1.如果沒有使用按鈕..buffer有辦法取值嗎 因為那個按鈕對我來說是破壞畫面...^_^ (整個表格畫面列印出來..有那個按鈕就是怪怪的) 2.我可以設很多 edit ...用上下左右鍵來選擇輸入任意選的 edit1 edit2 edit3 來取很多buffer1 buffer2 buffer3 的值嗎 對了 額外再請教一下我還沒讀的 listbox 控制項 1.是不是在 listbox 點選其中的一項後就取值了 2.程式跑一段時間後...要怎麼修改或增加 list 內的項目 再次的謝謝你..我可以不必再被卡在鍵盤的按鍵碼了
1. 上述的範例利用: case BN_CLICKED 來取值,表示按鈕按下去後作取值的動作 如果你要用其他方式取值,改變case即可,如: case xxxx 2. 可以 關於listbox: 1.如何為listbox取值,我只利用C#語言做過。未在dev C++中嘗試,故無法回答。 2.你可以利用一個叫SendMessage的函式達成此功能,詳情你可看書或google
謝謝~~ 不過....case xxxx 4個 xxxx 該填上甚麼? 看在我是新手的份上....明示一下啦 其他的我再奮力 google
這要看你的需求是什麼而定 比如,若你把 BN_CLICKED 改成 EN_CHANGE 那你每修改一次editbox的文字(而非按按鈕),訊息方塊就會跑出來一次 其餘還有許多,在微軟的文件都可查到: https://docs.microsoft.com/en-us/windows/win32/controls/en-update
謝謝提供好用的網址..我又可以瘋好幾天了 對了..能不能介紹幾本win32api的書呢 最好是中文版的(因為我的英文超爛的) 當然啦...如果有必讀卻也是英文版的也請介紹一下 看看網路字典能否幫上忙 因為目前我只找到 金禾出版 林隆煥著 視窗程式設計涵式庫 Win 32 API (這還是多年前訂到的...沒現貨) 總覺得還是不夠用 而書局大都是 vc c# .net....等等 我真的不知道這些書是不是有關 可以的話..就請介紹幾本 先說謝謝囉
這方面我就幫不上忙了 畢竟這不是我的主要領域 我也是需要用到時才在網路上找資料的
老師好~~ 新年快樂~~~~ 目前我又回到傷腦筋的原點了 我在多重文件中.. MDIChildWndProc 的 switch(Message) { case WM_CREATE: hedit1 = CreateWindow("EDIT", "在這邊輸入", WS_CHILD| WS_VISIBLE| ES_CENTER, 11,10, 138,18, hwnd,(HMENU)101, NULL,NULL); case WM_LBUTTONDOWN: char buffer[256] = {0}; GetWindowTextA(hedit1,buffer,256); MessageBox(NULL, buffer ,"您輸入的是:", MB_OK); 但就是抓不到我的輸入文字 是不是哪擺錯位置..... 我該怎麼處理?? 謝謝!! 新年快樂~~~~~~
你好,新年快樂 1. 有一個習慣要先養成: case XXXXX: 之後,要用大括弧{}包起來 2. 每個case括弧中的程式碼,末尾要打上一行break; 如: switch(Message) { case WM_CREATE: { hedit1 = CreateWindow("EDIT", "在這邊輸入",WS_CHILD| WS_VISIBLE| ES_CENTER, 11,10, 138,18,hwnd,(HMENU)101, NULL,NULL); break; } case WM_LBUTTONDOWN: { char buffer[256] = {0}; GetWindowTextA(hedit1,buffer,256); MessageBox(NULL, buffer ,"您輸入的是:", MB_OK); break; } } 你再試看看吧
我又做了些修改..可是仍然不通...我貼上我的碼...有空時請再幫我看一下 謝謝! main.cpp #include
#include
#include "main.h"
#define FIRSTCHILD 101
HWND hwndframe;
LPCTSTR szchild = "mdichild";
HMENU hmainmenu, heditmenu, hwinmenu;
HINSTANCE hinst;
LRESULT CALLBACK wndproc(HWND , UINT , WPARAM , LPARAM );
LRESULT CALLBACK childwndproc(HWND , UINT , WPARAM ,LPARAM );
int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance,LPSTR szcmdparam, int icmdshow) {
static TCHAR szappname[] = "MyApp";
HWND hwnd;
MSG msg;
WNDCLASSEX wndclass;
wndclass.cbSize = sizeof(wndclass);
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = wndproc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hinstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wndclass.lpszMenuName = "IDR_MENU1";
wndclass.lpszClassName = szappname;
wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&wndclass);
wndclass.lpfnWndProc = childwndproc;
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szchild;
if(!RegisterClassEx(&wndclass)) {
MessageBox(0, "Could Not Register Child Window", "Oh Oh...",
MB_ICONEXCLAMATION | MB_OK);
return -1;
}
hinst = hinstance;
hmainmenu = LoadMenu(hinst, "IDR_MENU1");
heditmenu = LoadMenu(hinst, "IDR_MENU2");
hwinmenu = GetSubMenu(heditmenu, 2);
hwnd = CreateWindow(szappname,"函示示範: Create MDIWindow",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
0, 0, hinstance, NULL);
if (hwnd == NULL){
MessageBox(0, "No Window", "Oh Oh...", MB_ICONEXCLAMATION | MB_OK);
return -1;
}
ShowWindow(hwnd, icmdshow);
UpdateWindow(hwnd);
while(GetMessage(&msg, NULL, 0, 0)) {
if (hwndframe || !TranslateMDISysAccel(hwndframe, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
LRESULT CALLBACK wndproc(HWND hwnd, UINT imsg, WPARAM wparam, LPARAM lparam)
{
static int num = 0, count = 0;
HWND hactivewnd;
switch(imsg)
{
case WM_CREATE:
{
CLIENTCREATESTRUCT ccs;
ccs.hWindowMenu = NULL;
ccs.idFirstChild = ID_CHILD;
hwndframe = CreateWindowEx(WS_EX_CLIENTEDGE,
"mdiclient", NULL,
WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE,
0,0,0,0,
hwnd, (HMENU)101, hinst, &ccs);
break;
}
return 0;
case WM_COMMAND:
switch(LOWORD(wparam))
{
case IDM_New:
{
HWND hwndchild;
TCHAR sztitle[81];
wsprintf(sztitle,"Document %d", ++num);
hwndchild = CreateMDIWindow((LPTSTR)szchild,sztitle,
WS_VISIBLE,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
CW_USEDEFAULT,hwndframe,hinst,0L);
if(count ==0)
{
SendMessage(hwndframe, WM_MDISETMENU,
(WPARAM)heditmenu,(LPARAM)hwinmenu);
}
count++;
break;
}
case IDM_Close:
{
hactivewnd = (HWND)SendMessage(hwndframe,
WM_MDIGETACTIVE,0,0);
if(hactivewnd)
{
SendMessage(hwndframe,WM_MDIDESTROY,
(WPARAM)hactivewnd,0);
count = count - 1;
if(count == 0)
{
SendMessage(hwndframe,WM_MDISETMENU,
(WPARAM)hmainmenu,(LPARAM)NULL);
DrawMenuBar(hwnd);
}
}
break;
}
case IDM_Hori:
TileWindows(hwndframe,MDITILE_HORIZONTAL,NULL,0,NULL);
break;
case IDM_Vert:
TileWindows(hwndframe,MDITILE_VERTICAL,NULL,0,NULL);
break;
case IDM_Cascade:
CascadeWindows(hwndframe,MDITILE_SKIPDISABLED,NULL,0,NULL);
break;
case IDM_Arrange:
ArrangeIconicWindows(hwndframe);
break;
case IDM_Demo:
MessageBox(hwnd,"函式示範","IDM_Demo",MB_OK);
break;
case IDM_Exit:
SendMessage(hwnd,WM_CLOSE,0,0);
break;
default:
hactivewnd = (HWND)SendMessage(hwndframe,
WM_MDIGETACTIVE,0,0);
if(IsWindow(hactivewnd))
SendMessage(hactivewnd,WM_COMMAND,wparam,lparam);
break;
}
break;
case IDM_CLOSE:
{
if(NULL != GetWindow(hwndframe,GW_CHILD))
{
MessageBox(hwnd,"請先關閉所有文件視窗","警告",MB_OK);
return 0;
}
DestroyWindow(hwnd);
break;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefFrameProc(hwnd, hwndframe, imsg, wparam, lparam);
}
LRESULT CALLBACK childwndproc(HWND hwnd, UINT umsg, WPARAM wparam,LPARAM lparam)
{
HDC hdc;
HWND hlong;
static HMENU hmenu;
COLORREF cr[] = {RGB(0,0,0),RGB(255,0,0),
RGB(0,255,0),RGB(0,0,255),RGB(0,255,255)
};
static COLORREF color;
static UINT prev = IDM_Black;
switch(umsg)
{
case WM_CREATE:
{
HWND hwndframe, hwndmain;
hwndframe = GetParent(hwnd);
hwndmain = GetParent(hwndframe);
hmenu = GetMenu(hwndmain);
hlong=CreateWindow(TEXT("edit"),TEXT("請在這裡打字"),
WS_VISIBLE | WS_CHILD,
10, 10, 100, 50,
hwnd, (HMENU) 1, NULL, NULL);
CreateWindow(TEXT("button"),TEXT("打字完按我"),
WS_VISIBLE | WS_CHILD,
10, 110, 100, 50, hwnd, (HMENU) 1, NULL, NULL);
break;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
hdc = BeginPaint(hwnd, &ps);
SetTextColor(hdc,color);
TextOut(hdc,180,10,"恭喜發財",8);
EndPaint(hwnd, &ps);
break;
}
case WM_MDIACTIVATE:
return 0;
case WM_DESTROY:
return 0;
case WM_COMMAND:
switch (HIWORD(wparam))
{
case BN_CLICKED:
{
char buffer[256] = {0};
GetWindowTextA(hlong,buffer,256);
MessageBox(NULL, buffer ,"您輸入的是:", MB_OK);
break;
}
}
break;
switch(LOWORD(wparam))
{
case IDM_Black:
case IDM_Green:
case IDM_Red:
case IDM_Blue:
case IDM_Cyan:
CheckMenuItem(hmenu,prev,MF_UNCHECKED);
prev = wparam;
CheckMenuItem(hmenu,prev,MF_CHECKED);
color = cr[wparam - IDM_Black];
InvalidateRect(hwnd,NULL,TRUE);
break;
}
break;
return DefMDIChildProc(hwnd, umsg, wparam, lparam);
return 0;
}
}
main.h
#define IDM_New 9170
#define IDM_Close 9171
#define IDM_Hori 9172
#define IDM_Vert 9173
#define IDM_Cascade 9174
#define IDM_Arrange 9175
#define IDM_Demo 9176
#define IDM_Exit 9177
#define IDM_CLOSE 9178
#define IDM_Black 9180
#define IDM_Green 9181
#define IDM_Red 9182
#define IDM_Blue 9183
#define IDM_Cyan 9184
#define ID_CHILD 50000
resource.rc
#include "main.h"
IDR_MENU1 MENU
{
POPUP "&File"
{
MENUITEM "&New", IDM_New
MENUITEM "&CLOSE", IDM_CLOSE
MENUITEM SEPARATOR
MENUITEM "E&xit", IDM_Exit
}
POPUP "&DEMO1"
{
MENUITEM "&IS DEMO", IDM_Demo
}
POPUP "&Window"//, GRAYED
{
MENUITEM "層疊 &Cascade", IDM_Cascade
MENUITEM "上下 Tile &Horizontal", IDM_Hori
MENUITEM "左右 Tile &Vertical", IDM_Vert
MENUITEM "整理 Arrange &Icons", IDM_Arrange
}
}
謝謝~~~
你所謂的"不通"是什麼情況?
當我按下 File -> New 後,無法建立子視窗 但有輸入視窗 而當我在輸入視窗輸入文字後按下打完字按我 buffer 抓不到我輸入的自 MessageBox 顯示出來的是空白 就是MessageBox有動作...沒內容 謝謝
老師好~~ 我已經在寫另一個版本的程式碼中找到問題並解決了 就是....忘了... 1. 以下這一行放在LRESULT CALLBACK WndProc之前: HWND handle; 仍然非常感謝你在年假中還幫我看成是碼 謝謝你~~~
不客氣~
老師好~~ 我又有幾個問題想要請教你.. 1.我把輸入的資料不用MessageBox(NULL, buffer ,"您輸入的是:", MB_OK)顯示 改從 case BN_CLICKED: TextOut(hdc,180,50, buffer,lstrlen(buffer))顯示 為什麼宣告buffer 必須也提到最上端宣告 而不能在LRESULT CALLBACK childwndproc()內宣告 case BN_CLICKED: 和 case BN_CLICKED: 不是都同在 LRESULT CALLBACK childwndproc() 內嗎? 2.char buffer[256] = {0}; 提到最上面宣告..可以執行 但為什麼我按下按鍵後沒辦法馬上顯示 而必須改變視窗大小後才顯示出來? 3.因為是多重視窗..若我同時要登記三份資料..按了三次開新檔案 前兩分的資料都會變成與第三份資料一樣 該怎樣宣告才能不管開了幾個新檔案..都有個別獨立的記憶體 4.如果我要輸入的是數值(浮點數)而不是文字 是否只能將文字轉成數字...還是可以直接宣告數值變數(如果可以該怎麼做?) 以上~~ 不好意思,打擾你的年假,也謝謝你!
哇~~有錯字 改從case WM_PAINT: TextOut(hdc,180,50, buffer,lstrlen(buffer))顯示 case WM_PAINT: 和 case BN_CLICKED: 不是都同在 LRESULT CALLBACK childwndproc() 內嗎?
1.2 WM_PAINT是message而非wparam,BN_CLICKED才是wparam。會不會你是寫到錯誤的switch裡面? 3. 我不曉得你開三個檔案是否真的有必要性... 就你的文字敘述來看,我覺得用一個vector或是矩陣來裝想輸入的資料就可以了 4. 一般是從文字轉成其他資料型態,其他方式我沒見過
我貼一下程式碼片段 #include
#include
#include "main.h"
#define FIRSTCHILD 101
HWND hwndframe;
LPCTSTR szchild = "mdichild";
HMENU hmainmenu, heditmenu, hwinmenu;
HWND hlong; ////宣告成全域
char szbuffer[256] = {0}; ////宣告成全域
HINSTANCE hinst;
LRESULT CALLBACK wndproc(HWND , UINT , WPARAM , LPARAM );
LRESULT CALLBACK childwndproc(HWND , UINT , WPARAM ,LPARAM );
.
.
.
LRESULT CALLBACK childwndproc(HWND hwnd, UINT umsg, WPARAM wparam,LPARAM lparam)
{
HDC hdc;
// char szbuffer[256] = {0}; // 移到全域
static HMENU hmenu;
COLORREF cr[] = {RGB(0,0,0),RGB(255,0,0),
RGB(0,255,0),RGB(0,0,255),RGB(0,255,255)
};
static COLORREF color;
static UINT prev = IDM_Black;
switch(umsg)
{
case WM_CREATE:
{
HWND hwndframe, hwndmain;
hwndframe = GetParent(hwnd);
hwndmain = GetParent(hwndframe);
hmenu = GetMenu(hwndmain);
hlong=CreateWindow(TEXT("edit"),TEXT("請在這裡打字"),
WS_VISIBLE | WS_CHILD,
10, 10, 100, 50,
hwnd, (HMENU) 1, NULL, NULL);
CreateWindow(TEXT("button"),TEXT("") /*("打完字請按我") */,
WS_VISIBLE | WS_CHILD,
500, 100, 160, 10, hwnd, (HMENU) 1, NULL, NULL);
break;
break;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
// hdc = GetDC(hwnd); 改變視窗尺寸,"恭喜發財"會不見
hdc = BeginPaint(hwnd, &ps);
SetTextColor(hdc,color);
TextOut(hdc,180,10,"恭喜發財",8);
TextOut(hdc,180,50, szbuffer,lstrlen(szbuffer)); // 改從這邊顯示
EndPaint(hwnd, &ps);
// ReleaseDC(hwnd,hdc);
break;
}
case WM_MDIACTIVATE:
{
return 0;
}
case WM_DESTROY:
return 0;
case WM_COMMAND:
switch (HIWORD(wparam))
{
case BN_CLICKED:
{
GetWindowTextA(hlong,szbuffer,256);
// MessageBox(NULL, buffer ,"您輸入的是:", MB_OK); // 不再在這邊顯示
break;
}
}
break;
switch(LOWORD(wparam))
{
case IDM_Black:
case IDM_Green:
case IDM_Red:
case IDM_Blue:
case IDM_Cyan:
CheckMenuItem(hmenu,prev,MF_UNCHECKED);
prev = wparam;
CheckMenuItem(hmenu,prev,MF_CHECKED);
color = cr[wparam - IDM_Black];
InvalidateRect(hwnd,NULL,TRUE);
break;
}
break;
}
return DefMDIChildProc(hwnd, umsg, wparam, lparam);
}
1.這樣不知道也沒有寫到錯誤的switch裡面
2.仍然想問但為什麼我按下按鍵後沒辦法馬上顯示
而必須改變視窗大小後才顯示出來?
3.如果用vector或矩陣...會不會又是用到同一個記憶體(就是又同一個vector).
就是會開啟很多頁面..才會朝多重文件方面顛蚾的走(像Excel開很多sheet 或AutoCad 開很多圖紙)
看樣子只能轉文字了....
好懷念
int n;
cin>> n;
1.2 你的buffer如果留在case WM_PAINT中或childwndproc()中,dev有給你什麼錯誤訊息嗎? 3. 每一個頁面所存放的資料,都有自己專屬的記憶體位置 假設資料是最簡單的string, 那麼宣告一個全域的vector<string> data; 第一個頁面的資料就存在data[0] 第二個頁面的資料就存在data[1] 以此類推 若資料型態有多個子項目,那麼就用類別來模擬,如: 宣告一個全域的vector<類別> data;
若放在WM_PAINT [Error] 'szbuffer' was not declared in this scope 指向這一行 GetWindowTextA(hlong,szbuffer,256); 若放在childwndproc()的最前端 沒異常碼 但讀不到值....沒顯示東西 (這就是以前我一直遇到的問題..讓我不知道錯在哪) 我現在想弄個SendMessage(hwnd,WM_PRINT,NULL,NULL);來觸發..可以馬上顯示 但....一直摸不到方法 還在試誤中....
若放在WM_PAINT [Error] 'szbuffer' was not declared in this scope 指向這一行 GetWindowTextA(hlong,szbuffer,256); ...就這一點我可以體會它在說甚麼.. 但... LRESULT CALLBACK childwndproc(HWND hwnd, UINT umsg, WPARAM wparam,LPARAM lparam) { HDC hdc; char szbuffer[256] = {0}; 為什麼會沒有編譯錯誤卻無法顯示內容...這就有點難以理解 我一直認為WM_PAINT 和 case BN_CLICKED: 都在childwndproc() 的大括弧內 應該是同一個 scope ... szbuffer 應該可以一直存在著...應該抓得到才對 這讓我在GetWindowTextA(hlong,szbuffer,256);繞了好久又好久..沒編譯錯誤卻不顯示 上網查了好久都摸不到問題點...直到你告訴我 szbuffer 要宣告為全域才可以.. 事後來想...宣告為全域是可以的...但為什麼必須宣告為全域就不懂了 雖然把很多東西都設為全域或許可以避掉目前的問題...但也會遇到被其他 程式碼修不小心改到他的值 像這種觀念(眉角)的問題還請老師指點一下....因為我真的腦補不起來.... . .
1. 我應該沒有告訴過你buffer要提升到全域變數 反之,你每一個case內都宣告一個專用的buffer如何呢? 2. 你在case BN_CLICKED:之中, 不是已經把顯示文字註解掉了嗎 // MessageBox(NULL, buffer ,"您輸入的是:", MB_OK); // 不再在這邊顯示
在第二則留言回答中 1. 以下這一行放在LRESULT CALLBACK WndProc之前: HWND handle; 2. 以下這一段程式碼放在 LRESULT CALLBACK WndProc的switch(Message) { 之內: case WM_CREATE: { handle=CreateWindow(TEXT("edit"),TEXT("請在這裡打字"),WS_VISIBLE | WS_CHILD, 10, 10, 100, 50, hwnd, (HMENU) 1, NULL, NULL); CreateWindow(TEXT("button"),TEXT("打字完按我"),WS_VISIBLE | WS_CHILD, 10, 110, 100, 50, hwnd, (HMENU) 1, NULL, NULL); break; } 雖然指的是HWND handle; 但handle我一直都是宣告在LRESULT CALLBACK WndProc內的 這給我很大的刺激...因為我所看的書或查的網路都沒出現過HWND handle;必須全域 所以buffer就有樣學樣...這麼來的 如同我第六則留言 case WM_LBUTTONDOWN: char buffer[256] = {0}; GetWindowTextA(hedit1,buffer,256); MessageBox(NULL, buffer ,"您輸入的是:", MB_OK); 但就是抓不到我的輸入文字 buffer 和 GetWindowTextA() MessageBox() 都在同一個case WM_LBUTTONDOWN: 內...但就是抓不到 (我有加大括號後才試) 也試過每一個case內都宣告一個專用的buffer...但就是抓不到我的輸入文字 只有把buffer改為全域....才可以成功抓到秀出文字 會// MessageBox(NULL, buffer ,"您輸入的是:", MB_OK); // 不再在這邊顯示 就是要在case WM_PAINT: TextOut(hdc,180,50, szbuffer,lstrlen(szbuffer)); // 改從這邊顯示 (buffer == szbuffer ..因版本不同.修改了一下命名)
我也不太清楚你現在真正的問題點在哪 只好直接依照你貼在#12的程式碼 重新回答你在#12的問題2 2.仍然想問但為什麼我按下按鍵後沒辦法馬上顯示 而必須改變視窗大小後才顯示出來? 按下按鍵後,edit中的文字被GetWindowTextA存到了szbuffer這個全域變數 但按鍵中,原本用來顯示該文字的程式碼已被註解,所以光按按鍵不會顯示文字 而拉動視窗產生了WM_PAINT訊息, 故case PAINT中的textout將szbuffer中的已存入的文字顯示出來 抓edit文字然後顯示,要兩個動作, (1) GetWindowTextA將文字存入buffer (2) 將buffer中的文字顯示。比如用messagebox或textout 12#的程式碼已將這兩個動作拆到兩個不同的區域 如果你不想按按鍵,想直接調整視窗大小就顯示文字, 那你要確保在TextOut(hdc,180,50, szbuffer,lstrlen(szbuffer))之前 有用GetWindowTextA將文字存入szbuffer 這種情況下,buffer不管在全域還是局域,程式都能執行
. 我想我是太急了,把想說的話都皺在一塊了 這次藉助於筆記本,可以慢慢的打字了 情境一: 當程式碼是這樣時... #include
#include
#include "main.h"
#define FIRSTCHILD 101
HWND hwndframe;
LPCTSTR szchild = "mdichild";
HMENU hmainmenu, heditmenu, hwinmenu;
HWND hlong; ////宣告成全域
.
.
.
LRESULT CALLBACK childwndproc(HWND hwnd, UINT umsg, WPARAM wparam,LPARAM lparam)
{
HDC hdc;
char szbuffer[256] = {0}; ///// 宣告在這裡時 局域 //////
.
.
case WM_PAINT:
{
PAINTSTRUCT ps;
hdc = BeginPaint(hwnd, &ps);
SetTextColor(hdc,color);
TextOut(hdc,180,10,"恭喜發財",8);
TextOut(hdc,180,50, szbuffer,lstrlen(szbuffer));
EndPaint(hwnd, &ps);
break;
}
.
.
case WM_COMMAND:
switch (HIWORD(wparam))
{
case BN_CLICKED:
{
GetWindowTextA(hlong,szbuffer,256);
TextOut(hdc,180,50, szbuffer,lstrlen(szbuffer));
MessageBox(NULL, szbuffer ,"您輸入的是:", MB_OK);
break;
}
}
char szbuffer[256] = {0}; 宣告在 CALLBACK childwndproc()時
MessageBox() 可以正常的顯示 szbuffer 的值
但
case WM_PAINT: 和 case BN_CLICKED: 內的TextOut(hdc,180,50, szbuffer,lstrlen(szbuffer));
都無法顯示 szbuffer 的值,就是編譯沒問題,卻不顯示TextOut()。
改變視窗大小也一樣不顯示
如上所示
GetWindowTextA(hlong,szbuffer,256);
TextOut(hdc,180,50, szbuffer,lstrlen(szbuffer));
MessageBox(NULL, szbuffer ,"您輸入的是:", MB_OK);
GetWindowTextA();和TextOut();黏在一起也不動作
倒是 MessageBox(NULL, szbuffer ,"您輸入的是:", MB_OK); 有動作
szbuffer在局域TextOut()顯示不出szbuffer的值,倒是 MessageBox()有動作
.
.
....我是分隔點.....
.
.
情境二:
當程式碼是這樣時...
#include
#include
#include "main.h"
#define FIRSTCHILD 101
HWND hwndframe;
LPCTSTR szchild = "mdichild";
HMENU hmainmenu, heditmenu, hwinmenu;
HWND hlong; ////宣告成全域
char szbuffer[256] = {0}; ////宣告成全域
case WM_COMMAND:
switch (HIWORD(wparam))
{
case BN_CLICKED:
{
GetWindowTextA(hlong,szbuffer,256);
TextOut(hdc,180,50, szbuffer,lstrlen(szbuffer));
MessageBox(NULL, szbuffer ,"您輸入的是:", MB_OK);
break;
}
}
char szbuffer[256] = {0}; ////宣告成全域
GetWindowTextA(hlong,szbuffer,256);
TextOut(hdc,180,50, szbuffer,lstrlen(szbuffer));
仍顯示不出szbuffer的值
MessageBox();也一樣有動作
.
.
....我是分隔點.....
.
.
情境三:
當程式碼是這樣時...
#include
#include
#include "main.h"
#define FIRSTCHILD 101
HWND hwndframe;
LPCTSTR szchild = "mdichild";
HMENU hmainmenu, heditmenu, hwinmenu;
HWND hlong; ////宣告成全域
char szbuffer[256] = {0}; ////宣告成全域
case WM_PAINT:
{
PAINTSTRUCT ps;
hdc = BeginPaint(hwnd, &ps);
SetTextColor(hdc,color);
TextOut(hdc,180,10,"恭喜發財",8);
TextOut(hdc,180,50, szbuffer,lstrlen(szbuffer));
EndPaint(hwnd, &ps);
break;
}
case WM_COMMAND:
switch (HIWORD(wparam))
{
case BN_CLICKED:
{
GetWindowTextA(hlong,szbuffer,256);
MessageBox(NULL, szbuffer ,"您輸入的是:", MB_OK);
break;
}
}
szbuffer宣告為全域,MessageBox()有動作
case WM_PAINT:TextOut(hdc,180,50, szbuffer,lstrlen(szbuffer));
在按下按鈕後,需要再改變一下視窗尺寸就可以顯示szbuffer的值
.
.
....我是分隔點.....
.
.
目前我算是(妥協的)接受有按鍵這個動作,但仍不希望有MessageBox()的動作
在情境一(szbuffer宣告為局域)和情境二(szbuffer宣告為全域)中,
TextOut()顯示不出來szbuffer的值,會讓我懷疑szbuffer到底有沒有抓到值
當然啦,在情境二中TextOut()是放在case BN_CLICKED:這會不會是造成TextOut()無效的原因?
還是到處放TextOut()都沒問題的?
只有在情境三TextOut()和MessageBox()都能正常工作,才讓我比較放心szbuffer有抓到值,
但無法在按下按鍵就能馬上顯示(還要改變一下視窗尺寸就有一點點點詭異)就覺得不順暢,
因為我完全不想要調整一下視窗尺寸才顯示szbuffer,我要的是直接顯示
.
.
....我是分隔點.....
.
.
我上一次的問題現在仍然想問,就是在情境一
LRESULT CALLBACK childwndproc(HWND hwnd, UINT umsg, WPARAM wparam,LPARAM lparam)
{
HDC hdc;
char szbuffer[256] = {0};
為什麼會沒有編譯錯誤卻無法顯示內容...這就有點難以理解
我一直認為WM_PAINT 和 case BN_CLICKED: 都在childwndproc() 的大括弧內
應該是同一個 scope ... szbuffer 應該可以一直存在著...應該抓得到才對
.
.
....我是分隔點.....
.
.
我完全不想要調整一下視窗尺寸才顯示szbuffer,我要的是直接顯示
能不能教一下在 case BN_CLICKED:用程式碼產生一個WM_PAINT訊息,
這樣才比較像正常的程式碼嘛...
.
.
.
至於開三個頁面的問題,等我跳進去vector一趟,看能不能又跳出來問問題....
以上~~
謝謝~~~~~
這樣看來我也不解其中原因 畢竟我沒碰到過這類問題 可惜是沒辦法幫到你了
老師這麼說...就讓我想到以前看過的網路文章 現在再把它找出來 1.不要再推薦 Dev-C++ 給新手了! 2.李大師您多久沒寫程式了 ? 一百個你不應該繼續用Dev C++的理由 尤其是第二篇文章的末端寫著... "然後看見這本書的介紹裡提到 在此強調我們用的程式語言是C語言,所使用的編譯器是Dev-C++4.9.9.2。讀者如果用錯了編譯器版本可能會出問題。" dev 是我選的..就當是踩到dev 編譯器的特色 反正 szbuffer全域宣告就好了 倒是能不能教一下...在 case BN_CLICKED:用程式碼產生一個WM_PAINT訊息 (不要叫我手動拉一下視窗喔)
老師好 我找到在 case BN_CLICKED:用程式碼產生一個WM_PAINT訊息 的方式 case WM_PAINT: { PAINTSTRUCT ps; // hdc = GetDC(hwnd); 改變視窗尺寸,"恭喜發財"會不見 hdc = BeginPaint(hwnd, &ps); SetTextColor(hdc,color); TextOut(hdc,180,10,"恭喜發財",8); TextOut(hdc,180,50, " ",25); // 清空之前szbuffer所顯示的內容 TextOut(hdc,180,50, szbuffer,lstrlen(szbuffer)); // 顯示新的輸入內容 EndPaint(hwnd, &ps); // ReleaseDC(hwnd,hdc); break; } case BN_CLICKED: { GetWindowTextA(hlong,szbuffer,256); TextOut(hdc,180,50, szbuffer,lstrlen(szbuffer)); // MessageBox(NULL, szbuffer ,"您輸入的是:", MB_OK); // 修改成不從MessageBox()顯示 // SendMessage(hwnd,WM_PAINT,0,0); // WM_PAINT 是無效的 InvalidateRect(hwnd, NULL, FALSE); // 觸發WM_PAINT 重繪畫面 break; } 不知道這個方式有沒有隱藏甚麼危險的地方....
這個我也沒什麼研究呢
還是非常謝謝老師的指導喔~~ 晚安~~~
不客氣
非常好的po文,推薦給你們看看 https://vscyw.com/index.php/product/gold-2/ https://vscyw.com/index.php/2022/04/07/cyyxm/ https://vscyw.com/index.php/2022/04/07/gmcy/ 更多詳情了解 ,可添加line: buy188
回饋您這方面資訊,我是從 PTT搜尋引擎的排名,看到大家推薦的內容而輾轉來到這, 不然每次看到一堆 Blog 文章,卻不知哪幾篇才是值得花時間一看的, 謝謝您用心分享的好文, 也回饋給您這實用的主題排名網站資訊,可查看與您 Blog 內容相關的排名好文,應該對寫 Blog 也有所幫助,期待您持續產出好文章 ^^ https://searchptt.cc/
感謝您的分享與支持。 不知您是打什麼關鍵字找到我這篇文章的?
老師好 又來請教問題了 char* yes; yes = "春秋" ; cout << "\n" << yes << "\n"; 這樣可以輸出 春秋 cin >> yes; cout << "\n" << yes << "\n"; 這樣不管我輸入甚麼字 就是都沒有顯示 char* yes; 這種型態的變數可以做輸入嗎? 如果可以的話該怎樣輸入.... 謝謝~
char* a = new char[10]; cin>>a; cout<<a; 其中的10是空間大小,看你的需求可自行調整。
想不到可以這麼使用 謝謝老師