⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sample13.c

📁 机械工业出版社 Lab Windows/CVI逐步深入与开发实例源代码
💻 C
字号:
#include <windows.h>
#include <formatio.h>
#include "inifile.h"
#include <ansi_c.h>
#include <cvirte.h> 
#include <utility.h>
#include <userint.h>
#include <stdio.h>
#include "sample13.h"
#include <libsupp.h>
#include <math.h>

//最多创建的线程数
#define MAXTHREADS 6
#define RADIUS 40

typedef struct tag_THREAD_INFO{
    int           ctrlID;             // Cavas控件ID号
    HANDLE        hThread;            //线程句柄
    unsigned int  CurrentValue;       //线程当前值
    int           IsRunning;          //线程状态
} THREAD_INFO;



static int panelHandle = 0;
static volatile int exiting   = 0;

//变量数组threadInfoArray储存各线程信息
THREAD_INFO threadInfoArray[MAXTHREADS] ;
//变量threadCount表示当前已创建线程数
int threadCount = 0;
//数组top 和left分别表示各线程Cavas控件的位置
int top[MAXTHREADS]={40,40,40,180,180,180};
int left[MAXTHREADS]={20,140,260,20,140,260};

int color;

Point start,end;

//INI文本数据
IniText myInifile;

int ShutdownApplication(void);

DWORD WINAPI MyThread(LPVOID item);

int __stdcall WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                       LPSTR lpszCmdLine, int nCmdShow)
{
    //习题添加的代码
    int status;
    int threadStatus[MAXTHREADS];
    //添加代码结束
    
    int i,num;
    
    for(i=0;i<MAXTHREADS;i++)
           threadInfoArray[i].IsRunning=-1;
    
    if (InitCVIRTE (hInstance, 0, 0) == 0)    
        return -1;   

    if ((panelHandle = LoadPanel (0, "sample13.uir", PANEL)) < 0)
        return -1;

    //创建列表
    if (!(myInifile = Ini_New (0)))
       {
         //创建失败,显示出错信息并退出
         MessagePopup("Inifile","Error allocating memory for Inifile");
         return 0;
       }   
            
    //从sample13.ini文件中读取数据到列表
    if (!Ini_ReadFromFile (myInifile, "sample13.ini"))
       {

		 //读取数据成功
         //从列表中读取上次程序关闭时的线程数
		 Ini_GetInt (myInifile, "ThreadInfo", "threadNum", &num);
         if(num<0) num=0;
         if(num>6) num=6;

          //习题添加的代码
         //从列表中读取上次程序关闭时的线程状态
		 Ini_GetInt (myInifile, "ThreadInfo", "thread1", &threadStatus[0]);
		 Ini_GetInt (myInifile, "ThreadInfo", "thread2", &threadStatus[1]);
		 Ini_GetInt (myInifile, "ThreadInfo", "thread3", &threadStatus[2]);
		 Ini_GetInt (myInifile, "ThreadInfo", "thread4", &threadStatus[3]);
		 Ini_GetInt (myInifile, "ThreadInfo", "thread5", &threadStatus[4]);
		 Ini_GetInt (myInifile, "ThreadInfo", "thread6", &threadStatus[5]);
         //添加代码结束
         
         
         //循环调用CreateCallback函数num次
         for(i=0;i<num;i++)
            CreateCallback (panelHandle, PANEL_CREATE, EVENT_COMMIT,
                            NULL,  0, 0);
            
         //习题添加的代码
		 //设置线程状态,暂停或者运行
         for(i=0;i<num;i++)
            if(threadStatus[i]==0)
            {
			    status=SuspendThread(threadInfoArray[i].hThread);
			    
			    if(status<0)
				  MessagePopup ("Error", "Suspend thread error!");
				else
                  threadInfoArray[i].IsRunning=0;
            }
            
         RingCallback (panelHandle, PANEL_RING, EVENT_COMMIT,0,0,0);
        //添加代码结束
      }   

    DisplayPanel (panelHandle);
    RunUserInterface ();
	 
	//将线程数储存到列表中
	Ini_PutInt (myInifile, "ThreadInfo", "threadNum", threadCount);
	
    //习题添加的代码
	//将线程状态储存到列表中
    Ini_PutInt (myInifile, "ThreadInfo", "thread1", threadInfoArray[0].IsRunning);
	Ini_PutInt (myInifile, "ThreadInfo", "thread2", threadInfoArray[1].IsRunning);
	Ini_PutInt (myInifile, "ThreadInfo", "thread3", threadInfoArray[2].IsRunning);
	Ini_PutInt (myInifile, "ThreadInfo", "thread4", threadInfoArray[3].IsRunning);
	Ini_PutInt (myInifile, "ThreadInfo", "thread5", threadInfoArray[4].IsRunning);
	Ini_PutInt (myInifile, "ThreadInfo", "thread6", threadInfoArray[5].IsRunning);
    //添加代码结束
	
    //将列表的数据储存到INI文件中
    Ini_WriteToFile (myInifile, "sample13.ini");

    //在退出程序前终止已创建的线程
    ShutdownApplication();  
    
    return 0;
}

int CVICALLBACK CreateCallback (int panel, int control, int event,
    void *callbackData, int eventData1, int eventData2) 
{
    //定义变量
    char  threadName[50];
    int   ctrlID;
    DWORD threadID;
    
    switch (event) {
        case EVENT_COMMIT:

            //判断是否已经创建了6个线程
            if (threadCount==MAXTHREADS) 
            {
				//显示出错信息,并返回
				MessagePopup ("Error", "Maximal threads has createed!");
                return 0;
            }    
            
            //创建新线程,MyThread为线程函数,其定义稍后介绍           
            threadInfoArray[threadCount].hThread = CreateThread( 
                NULL, 0,
                (LPTHREAD_START_ROUTINE)MyThread,
                (LPVOID)threadCount, 0,
                (LPDWORD)&threadID);
                        
            //创建线程是否成功
            if (threadInfoArray[threadCount].hThread) 
            {   
                //创建线程成功
                //创建新Cavas控件
                sprintf(threadName, "Thread %d", threadCount+1);
	     		threadInfoArray[threadCount].ctrlID = 
					  NewCtrl (panel, CTRL_CANVAS, threadName, top[threadCount],
							   left[threadCount]);
		
                //设置threadInfoArray相关参数
                threadInfoArray[threadCount].IsRunning=1;
				threadInfoArray[threadCount].CurrentValue=0;
				
                //已创建线程数加1
                threadCount++;
                
                //向控件RING添加新项目
                InsertListItem (panel, PANEL_RING, -1, threadName, threadCount);
				
                //设置RESUMEORSUSPEND控件值为0
                SetCtrlVal (panel, PANEL_RESUMEORSUSPEND, 0);
				
                //如果是创建第一个线程,设置TERMINATE
                //RING、RESUMEORSUSPEND控件有效
				if(threadCount==1)
				{
				  SetCtrlAttribute (panel, PANEL_TERMINATE, ATTR_DIMMED, 0);
				  SetCtrlAttribute (panel, PANEL_RING, ATTR_DIMMED, 0);
				  SetCtrlAttribute (panel, PANEL_RESUMEORSUSPEND, ATTR_DIMMED, 0);
            	}
            }
            else 
                //创建线程失败,显示出错信息
                MessagePopup ("Error", "Creating thread fail!");
            
            break;
    }
    return 0;
}

//在退出程序前调用该函数关闭已运行线程
int ShutdownApplication(void)
{
    int index=0 , exitCode;
    double startTime;
    
    exiting = 1;
    
    for(index=0;index<MAXTHREADS;index++)
	{
	   if(threadInfoArray[index].hThread)
	   {
	       
	       if(!threadInfoArray[index].IsRunning)
              ResumeThread(threadInfoArray[index].hThread);
              
	       startTime=Timer();
	       
           GetExitCodeThread(threadInfoArray[index].hThread, &exitCode);
       
           while ((exitCode==STILL_ACTIVE) && ((Timer()-startTime) < 10.0)) 
           {
               Sleep(0);
               GetExitCodeThread(threadInfoArray[index].hThread, &exitCode);
           } 
       
          if (exitCode == STILL_ACTIVE)  
               TerminateThread(threadInfoArray[index].hThread, 0);
       
          CloseHandle(threadInfoArray[index].hThread);
          
          threadInfoArray[index].hThread = 0;
       }
	   
	}
    return 0;
}   

//线程函数,线程运行时执行该函数,
//该函数实现在CANVAS上显示彩色旋转器
DWORD WINAPI MyThread(LPVOID item)
{
   while(!exiting){
   
       threadInfoArray[(int)item].CurrentValue++;
       
       if(InStandaloneExecutable())
          {
	         if(threadInfoArray[(int)item].hThread)
                {
                	threadInfoArray[(int)item].CurrentValue+=5;
                	
                	if(threadInfoArray[(int)item].CurrentValue>360)
	                    threadInfoArray[(int)item].CurrentValue-=360;
	                    
	                start.x=25;
                	start.y=25;
                	
                	end.x=(int)(RADIUS*
                	      cos(PI*(threadInfoArray[(int)item].CurrentValue)/180.0)+RADIUS);
                  	end.y=(int)(RADIUS*
                  	      sin(PI*(threadInfoArray[(int)item].CurrentValue)/180.0)+RADIUS);;

                    color = MakeColor(255*rand()/RAND_MAX, 
                             255*rand()/RAND_MAX, 255*rand()/RAND_MAX);
                             
					SetCtrlAttribute (panelHandle, threadInfoArray[(int)item].ctrlID,
									  ATTR_PEN_COLOR, color);
					  
					CanvasDrawLine (panelHandle, threadInfoArray[(int)item].ctrlID, start,
									end);
               }
         }
        Sleep(0);
    }   
    return(0);
}

int CVICALLBACK TerminateCallback (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
	int status,index;
	
	switch (event)
		{
		case EVENT_COMMIT:
		
			 //判断当前是否存在线程 
			 if(threadCount>0)
              {
                  //终止最新创建的线程
                  status=TerminateThread(threadInfoArray[threadCount-1].hThread,0);   
                 
                  if(status==FALSE)
                      //操作失败,显示出错信息
			          MessagePopup ("Error", "Terminate thread error!");
   		          else
			       {
                     //终止线程成功
                     //删除该线程的Canvas控件
			         DiscardCtrl (panel, threadInfoArray[threadCount-1].ctrlID);
			         
                     threadInfoArray[threadCount-1].IsRunning=-1;

                     //删除RING控件中表示该线程的项
					 GetIndexFromValue (panel, PANEL_RING, &index, threadCount);
					 DeleteListItem (panel, PANEL_RING, index, 1);
					 
                     //当前线程数减一
                     threadCount--;
			         
                     //如果线程数为0,设置控件TERMINATE、
                     //RING、RESUMEORSUSPEND无效
				     if(threadCount==0)
				       {
						 SetCtrlAttribute (panel, PANEL_TERMINATE, ATTR_DIMMED, 1);
				         SetCtrlAttribute (panel, PANEL_RING, ATTR_DIMMED, 1);
				         SetCtrlAttribute (panel, PANEL_RESUMEORSUSPEND, ATTR_DIMMED, 1);
            	       }
			       }
			   }
			break;
		}
	return 0;
}

int CVICALLBACK ResumeOrSuspendCallback (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
	int value,status,style;
	
	switch (event)
		{
		case EVENT_COMMIT:
		
              //获取控件RING和RESUMEORSUSPEND的值
              GetCtrlVal (panel, PANEL_RING, &value);
			  GetCtrlVal (panel, PANEL_RESUMEORSUSPEND, &style);
			  
              //判断是暂停还是继续线程
              if(style)
              {
			    //暂停线程
			    status=SuspendThread(threadInfoArray[value-1].hThread);
			    
			    if(status<0)
				  //操作失败,显示出错信息 
				  MessagePopup ("Error", "Suspend thread error!");
				else
                  //储存线程状态
                  threadInfoArray[value-1].IsRunning=0;
				
			  }
			  else
			  {
  			    //继续线程
  			    status=ResumeThread(threadInfoArray[value-1].hThread);
                
			    if(status<0)
				  //操作失败,显示出错信息 
				  MessagePopup ("Error", "Resume thread error!");
				else
                  //储存线程状态
                  threadInfoArray[value-1].IsRunning=1;
			  }
			break;
		}
	return 0;
}

int CVICALLBACK RingCallback (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
	int value;
	
	switch (event)
		{
		case EVENT_COMMIT:
		
			  //获取RING控件的值
			  GetCtrlVal (panel, PANEL_RING, &value);
			  
              //根据IsRunning值设置RESUMEORSUSPEND控件的值
              if(threadInfoArray[value-1].IsRunning)
			   SetCtrlVal (panel, PANEL_RESUMEORSUSPEND, 0);
			  else
			   SetCtrlVal (panel, PANEL_RESUMEORSUSPEND, 1);
			   
			break;
		}
	return 0;
}

int CVICALLBACK PanelCallback (int panel, int event, void *callbackData,
		int eventData1, int eventData2)
{
	switch (event)
		{
		case EVENT_CLOSE:
		
            QuitUserInterface (0);
            
			break;
		}
	return 0;
}

int CVICALLBACK QuitCallback (int panel, int control, int event,
        void *callbackData, int eventData1, int eventData2) {
    
    switch (event) {
        case EVENT_COMMIT:
        
            QuitUserInterface (0);
            
        break;
    }
    
    return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -